Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

Delegate problem invoked in a class (dll) : get_enabled can only be called from the main thread.

Discussion in 'Scripting' started by laurent-clave, Feb 17, 2015.

  1. laurent-clave

    laurent-clave

    Joined:
    Jul 18, 2011
    Posts:
    280
    Hi,

    I have a class for use pipes with unity and other app.
    This app is used in .dll (Placed in Plugins/)
    Work fine beetwen two ASP app.

    The dll code :
    Code (csharp):
    1.  
    2. public class PipeServer {
    3.         public delegate void DelegateMessage(string Reply);
    4.         private event DelegateMessage _pipeMessage;
    5.         private string _pipeName;
    6.  
    7.         public string debugStr;
    8.  
    9.         private void createPipeServer() {
    10.             try {
    11.                 NamedPipeServerStream pipeServer = new NamedPipeServerStream(_pipeName, PipeDirection.InOut, 1, PipeTransmissionMode.Message, PipeOptions.Asynchronous);
    12.                 pipeServer.BeginWaitForConnection(new AsyncCallback(WaitForConnectionCallBack), pipeServer);
    13.             } catch (Exception e) {
    14.                 throw new Exception(e.Message);
    15.             }
    16.         }
    17.  
    18.         public void Listen(string pipeName, DelegateMessage pipeMessage) {
    19.             try {
    20.                 _pipeName = pipeName;
    21.                 _pipeMessage = pipeMessage;
    22.                 createPipeServer();
    23.             } catch (Exception e) {
    24.                 throw new Exception(e.Message);
    25.             }
    26.         }
    27.  
    28.         private void WaitForConnectionCallBack(IAsyncResult iar) {
    29.             try {
    30.                 NamedPipeServerStream pipeServer = (NamedPipeServerStream) iar.AsyncState;
    31.                 pipeServer.EndWaitForConnection(iar);
    32.                 byte[] buffer = new byte[255];
    33.                 pipeServer.Read(buffer, 0, 255);
    34.                 string stringData = Encoding.UTF8.GetString(buffer, 0, buffer.Length);
    35.                 pipeServer.Close();
    36.                 pipeServer = null;
    37.          
    38.                 // PROBLEM :
    39.                 _pipeMessage(stringData);
    40.  
    41.                 createPipeServer();
    42.             } catch (Exception e) {
    43.                 throw new Exception(e.Message);
    44.             }
    45.  
    46.         }
    47.     }
    48.  
    And the code in unity :
    Code (csharp):
    1.  
    2. PipeServer pipeServer;
    3.  
    4.     void Start()
    5.     {
    6.         try {
    7.             pipeServer = new PipeServer();
    8.             pipeServer.Listen("pipe_test", delegate(string reply){
    9.                 debugText.text = "Réponse:"+reply;
    10.             });
    11.         }
    12.         catch(Exception e)
    13.         {
    14.             debugText.text = "Erreur : " + e.Message;
    15.         }
    16.     }
    17.  
    18.  
    When i send a message with clientPipe, unity show this error :
    'get_enabled can only be called from the main thread.'

    The problem is this line :
    Code (csharp):
    1.  
    2. _pipeMessage(stringData);
    3.  
    With
    Code (csharp):
    1.  
    2. _pipeMessage.Invoke(stringData);
    3.  
    same problem..

    It's a thread problem. A solution ?
     
  2. Dantus

    Dantus

    Joined:
    Oct 21, 2009
    Posts:
    5,667
    It seems that _pipeMessage calls MonoBehaviour instances. As Unity is not thread safe, this can only be done in the main thread. What you may try is to pass those calls to the main thread and let them be executed there.
     
  3. laurent-clave

    laurent-clave

    Joined:
    Jul 18, 2011
    Posts:
    280
    That's what I think :(
    But how to use MonoBehaviour in another thread?
     
  4. laurent-clave

    laurent-clave

    Joined:
    Jul 18, 2011
    Posts:
    280
    This is because I use a GUI element in another thread?
    Code (csharp):
    1.  
    2. pipeServer.Listen("pipe_test", delegate(string reply){
    3.                 debugText.text = "Réponse:"+reply;//<-----
    4.             });
    5.  
     
  5. laurent-clave

    laurent-clave

    Joined:
    Jul 18, 2011
    Posts:
    280
    This solution works.
    Code (csharp):
    1.  
    2. pipeServer.Listen("pipe_test", delegate(string reply){
    3.                 //debugText.text = "Réponse:"+reply;
    4.                 Debug.Log(Reply);
    5.             });
    6.  
     
  6. laurent-clave

    laurent-clave

    Joined:
    Jul 18, 2011
    Posts:
    280
    How can I use monobehaviour method with other desynchronized method?
     
  7. Dantus

    Dantus

    Joined:
    Oct 21, 2009
    Posts:
    5,667
    You can't use MonoBehaviour in any other thread. A solution is to buffer all the information and then use it from the main thread.
     
  8. laurent-clave

    laurent-clave

    Joined:
    Jul 18, 2011
    Posts:
    280
    Ok thank Dantus !