Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 12 Next capture
2021 2022 2023
1 capture
12 Jun 22 - 12 Jun 22
sparklines
Close Help
  • 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 ins$$anonymous$$d ? 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.

Follow this Question

Answers Answers and Comments

28 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

Related Questions

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

Raycasting at regular intervals with a frequency above the framerate. 0 Answers

Calling back to main thread from editor script 0 Answers

FixedUpdate logic step by step 1 Answer

Given volume dimensions and direction, how to determine if Vector3 is contained 2 Answers


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges