• Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
  • Help Room /
avatar image
0
Question by Skflowne · Sep 03, 2015 at 03:58 PM · c#threadsthreading

Using BackgroundWorker with Unity, Completed not running on Main thread ?

I'm working on an app that communicates heavily with an API. In order to get the data from the API the app first has to parse the whole JSON it receives. I'm looking into moving the parsing part in a worker thread so it doesn't create hiccups in the UI.

Now I know Unity's API is not thread safe. But I've looked at the BackgroundWorker class which is supposed to run a work function on a separate worker thread and a completed function that should run on the same thread the worker was created on.

But it turns out the completed function won't run on the main thread, it is actually running on the same worker thread which is definitely what I'm trying to avoid/bypass.

I'm testing this on a case where I have my ChallengesManager polling the server for a list of challenges, once received, I start the worked thread to parse and register the challenges in a Dictionnary>

  void OnChallengesLoaded(APIResponse r, Hashtable args){
         ResetChallengesList();
         Debug.Log("Current thread [Main] : " + System.Threading.Thread.CurrentThread.ManagedThreadId);
 
         InitWorker();
 
         JSONTask t = new JSONTask();
         t.toParse = r.body;
 
         bWorker.RunWorkerAsync(t);
 
         Debug.Log("Current thread [AfterStartBackground] : " + System.Threading.Thread.CurrentThread.ManagedThreadId);
 }

Then I have those two functions to do the work and for after it's done :

 void Worker_DoWork(object sender, DoWorkEventArgs e){
         Debug.Log("Starting work in background");
         JSONTask t = (JSONTask) e.Argument;
         Debug.Log("Current thread [Work] : " + System.Threading.Thread.CurrentThread.ManagedThreadId);
         e.Result = t.Parse();
     }
 
     void Worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e){
         Debug.Log("Work done !");
         JSONNode node = (JSONNode) e.Result;
         if(node != null){
             RegisterChallenges(node, "toPlay");
             RegisterChallenges(node, "waitingForOpponent");
             RegisterChallenges(node, "finished");
             RegisterChallenges(node, "toBeReviewed");
         }
         Debug.Log("Challenges retrieved ! Waiting : " + challenges["waitingForOpponent"].Count + " Ready : " + challenges["toPlay"].Count + " Finished : " + challenges["finished"].Count);
         Debug.Log("Current thread [Completed] : " + System.Threading.Thread.CurrentThread.ManagedThreadId);
         /*if(OnChallengesRetrieved != null){
             OnChallengesRetrieved(challenges);
         }*/
 
 
     }

Then I have this function for initializing the worker :

 void InitWorker(){
         Debug.Log("Current thread [InitWorker] : " + System.Threading.Thread.CurrentThread.ManagedThreadId);
         bWorker = new BackgroundWorker();
         bWorker.DoWork += new DoWorkEventHandler(Worker_DoWork);
         bWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(Worker_RunWorkerCompleted);
     }

And I also have this JSONTask class to encapsulate the parsing task :

 public class JSONTask {
 
     public string toParse;
 
     public JSONNode Parse(){
         return JSON.Parse(toParse);
     }
 }

Now the output of this is not really what I expect :

 Current thread [Main] : 1
 Current thread [InitWorker] : 1
 Current thread [Work] : 5
 Current thread [AfterStartBackground] : 1
 Challenges retrieved ! Waiting : 18 Ready : 5 Finished : 5
 Current thread [Completed] : 2

So the completed is not back on the main thread, and it's not even on the worker thread either. If I launch this whole process once more I get the completed on the same worker thread but still not going back to main thread.

Everything I read about background workers says it should go back to the thread it was created in, but that is simply not the case here and I have no idea why. Please help me :D

Comment
Add comment
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users

1 Reply

· Add your reply
  • Sort: 
avatar image
0
Best Answer

Answer by Dave-Carlile · Sep 03, 2015 at 05:54 PM

It sounds like there may be issues using BackgroundWorkers when a Form isn't available. Looking at the comments under the documentation for the 2.0 framework:

If you have a class that uses BackgroundWorker objects and want to do unit tests on the class using VS unit testing framework - you need to instantiate a Form object - otherwise the RunWorkerComplete event will happen in random threads as opposed to the expected main thread.

That's in the context of unit testing, but I would imagine that would be an issue in any case where you don't have the Form object.

Comment
Add comment · Show 2 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image Skflowne · Sep 04, 2015 at 12:30 PM 0
Share

That seems to be the problem yes, what can I use instead ? Tasks ?

avatar image Dave-Carlile · Sep 04, 2015 at 12:46 PM 0
Share

I'm not sure if those are in the 2.0 framework?

Another option is to find an implementation of a thread safe queue. Just use a normal thread and when it's done create some object instance to hold the results and add it to the queue. In some Update method, periodically pull items from the queue and do what you need to with the results.

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Welcome to Unity Answers

The best place to ask and answer questions about development with Unity.

To help users navigate the site we have posted a site navigation guide.

If you are a new user to Unity Answers, check out our FAQ for more information.

Make sure to check out our Knowledge Base for commonly asked Unity questions.

If you are a moderator, see our Moderator Guidelines page.

We are making improvements to UA, see the list of changes.



Follow this Question

Answers Answers and Comments

29 People are following this question.

avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image

Related Questions

How to integrate threading with a www query for a UWP app? 1 Answer

How can I thread this function? 0 Answers

Wait for value to not be null until thread finishes 0 Answers

Runtime errors on thread not showing 1 Answer

Best way to run a long algorithm in the background? 1 Answer

  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges