2
\$\begingroup\$

I have some custom networking classes which I'm trying to use in a unity game (c#). The network class raises events, which I want to subscribe to in the game code. However, whenever I try to do anything substantial in response to an event, I'm running into and error like this:

SomeFunction can only be called from the main thread

How can I get this to work? Presumably I have to communicate the event back to the main thread in some synchronous fashion. Is there a 'best practice' way of doing this in Unity?

\$\endgroup\$

2 Answers 2

3
\$\begingroup\$

So I solved this by writing the events to a queue, and then processing the queue synchronously during an update in the main thread. If there are other/better approaches though, I'd be happy to hear them.

\$\endgroup\$
1
  • \$\begingroup\$ Can you include a concise portion of your solution? You have a helpful question and solution here, it would be good to make it as useful as possible for the next person who runs into the error. \$\endgroup\$ Commented Jan 8, 2015 at 16:41
1
\$\begingroup\$

I had a similar issue and this post helped me solve the same problem, I will share the specifics of the solution as I understand them.

My System.Process event-listening function triggered the "can only be called from the main thread" issue when I tried to call the delegate function.

private static void RunningProcess_OutputDataReceived (object sender, DataReceivedEventArgs e) {
    if(dataCallback != null) {
        dataCallback(e.Data);
    }
}

So instead of calling it from that function, I assign it to a static variable:

private static void RunningProcess_OutputDataReceived (object sender, DataReceivedEventArgs e) {
    if(dataCallback != null) {
        outputDataToSend = e.Data;
    }
}

And then call the delegate from Update():

void Update () {
    if(!string.IsNullOrEmpty(outputDataToSend)) {
        dataCallback (outputDataToSend);
        outputDataToSend = null;
    }
}

This solution is not reliable as the above one is, because if the OutputDataReceived function gets called multiple times before Update, only the most recent data packet will be forwarded. Enqueuing the incoming callbacks as UpTheCreek did is a good way around that, but this solution is very simple and lets you get past the fundamental issue.

\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .