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.

Unity Threading Helper

Discussion in 'Assets and Asset Store' started by Marrrk, May 21, 2011.

  1. ChrisBurt

    ChrisBurt

    Joined:
    Aug 27, 2011
    Posts:
    2
    Hi, I would appreciate some clarification about when 'ShouldStop' is true. I am doing things just like the simple examples in the first post.

    My thread is run in a script on a gameobject that calls DontDestroyOnLoad. That's my 'game manager', which will exist for the whole game. Then, I load scenes using Application.LoadLevel to proceed through my game (but my game manager stays). I hope to keep the thread running until the application quits or I hit the Stop button in the editor.

    When I play in the editor, the thread seems to stop as soon as I load another scene. When I build and run an application, it seems to keep going after loading another scene. Is this expected?

    Is there a way to keep my thread going in editor, even when LoadLevel is called?

    UTH is sweet! Thanks!
     
  2. Marrrk

    Marrrk

    Joined:
    Mar 21, 2011
    Posts:
    1,032
    @Fher:

    Do compare two object instances you could also use System.Object.ReferenceEquals(a, b) which does not need to be run on the main thread, with this you could spare many CPU cycles as you dont need to dispatch any operations onto the main thread (your current solution does this internal).

    @ChristBurt:

    If you want a persistent thread you should not use the UTH Class, instead you should manage the UTH Threads yourself: Have a look at the first post in this thread to see how it is done.

    The UTH Class will dispose all threads when OnDestroy will be called on the UTH Component, you could try to call DontDestroyOnLoad on the UTH Class, which will not destroy the UTH object when loading a new scene:

    Code (csharp):
    1. DontDestroyOnLoad(UnityThreadHelper.Instance.gameObject);


    You also can enhance the existing UTH Component by adding [ExecuteInEditMode] above the class declaration. But I am not sure how this alters the OnDestroy behaviour. I suspect this will not work and you need to create an own class for persistent UTH threads.
     
    Last edited: Aug 16, 2013
  3. truesoldersprit

    truesoldersprit

    Joined:
    Aug 23, 2013
    Posts:
    10
    Hello, I'm very thank you about your sharing.

    This is what I'm looking for.
    Now I'm trying to process my thread with your class.

    The implement of threading form your code is a few lines.

    Here are the lines with c#.

    public class csThreadProcess:MonoBehaviour{


    UnityThreading.ActionThread myThread;

    void Start()
    {
    ......
    myThread = UnityThreadHelper.CreateThread(ThreadUpdate);
    }

    void ThreadUpdate()
    {
    }

    }

    But it outputs an errors.

    The call is ambiguous between thefollowing methods or properties: 'UnityThreadHelper.CreateThread(System.Func<System.Collections.IEnumerator>)' and 'UnityThreadHelper.CreateThread(System.Action)'

    Please solve this problem for me quickly.

    (PS)
    I would like to use this widely If there is no bug as a standard Api.
    And I hope to be helped from you very much in thread processing.
    After this errors passed, I would like to repay about your deserved technology by purchasing your Asset Version.
    Anyhow, Please help me very much!
    And If you have any document about this UnityThreadHelper detail, Please send a mail to "trueliveagain@gmail.com"
    I'm waiting for you.
     
    Last edited: Aug 23, 2013
  4. Marrrk

    Marrrk

    Joined:
    Mar 21, 2011
    Posts:
    1,032
    Hi there, this should work:

    myThread = UnityThreadHelper.CreateThread(() => ThreadUpdate());

    I hope that helped :)
     
  5. truesoldersprit

    truesoldersprit

    Joined:
    Aug 23, 2013
    Posts:
    10
    :DOh, I'm waiting for you for a long time.
    Anyhow, Thank you for your kind reply
    I'll try it just now.

    Yes, It's work.
    But, I have tried to exit this thread, It doesn't work well.

    hum...

    I would like to start my thread in Update function.
    And When my thread is finished it's work and Update function is called,It must to be started again.

    Then, how can I implement it with your function?
    Please help me!

    If you have spare time, Please explain how much it has belief.
    As for technical problems, I'll ask you when I have problems.
    But I wanna know that It can work without any bugs at first.

    Regards.
     
    Last edited: Aug 24, 2013
  6. Marrrk

    Marrrk

    Joined:
    Mar 21, 2011
    Posts:
    1,032
    Hi there,

    you should provide me your code you have problems with ;)

    The Thread will have multiple ways to be exited, the simplest is to that the thread will receive a notification which the thread needs to check and abort when received. The other is that the thread will be notified to shutdown and has a given time to handle this notification before it will be forcefully terminated.

    The paragraph with the Update function was hard to understand but I believe you simply want a thread which runs infinite/until stopped. Is this correct?

    In this case you need this in your thread function:

    Code (csharp):
    1.  
    2. void ThreadUpdate()
    3. {
    4.   while (!UnityThreading.ThreadBase.CurrentThread.ShouldStop)
    5.   {
    6.     ..
    7.   }
    8. }
    9.  
    The UTH should work with currently no known bugs, of course bugs may appear, but the last known bug has been fixed and further problems will too be solved as fast as possible.
     
  7. truesoldersprit

    truesoldersprit

    Joined:
    Aug 23, 2013
    Posts:
    10
    Thanks you. Marrrk.

    About your last answer, It's OK.
    I have purchased your Asset Version.

    Sorry about my wrong explanation about what I wanna know.

    I'm explaining in detail at follow.

    public class csThreadProcess:MonoBehaviour{

    void Myfunc()
    {
    // This func will take for a few times.
    for(int i=0;i<100000000000;i++)
    {
    Debug.Log("Every Calculation");
    }
    }

    void Update() // this is called per 0.2s, as you know
    {
    if(how?) // It is ended running Myfunc()?
    {
    // call Myfunc();
    }
    }

    }

    So, After Myfunc is called from prev Update() function, When the next Update() func is called, If the Myfunc() is running because It is not ended their all execution, My func must be not called.
    And It's running is ended, Then, When the next Update() is called, Myfunc must be called.

    How can I solve this problem?

    Sorry about my bad English.
     
    Last edited: Aug 25, 2013
  8. Marrrk

    Marrrk

    Joined:
    Mar 21, 2011
    Posts:
    1,032
    Hi there, I suggest you dont use the CreateThread Method and use instead the TaskDistributor:

    Code (csharp):
    1.  
    2. UnityThreading.Task task;
    3. ...
    4. void Update()
    5. {
    6.   if (task == null || task.HasEnded)
    7.     task = UnityThreadHelper.TaskDistributor.Dispatch(() => ThreadFunc());
    8. }
    9.  
    The TaskDistributor ensures that you do not create a new thread, every time you want to rerun your thread function, which gives you a little bit more performance (Creating threads is expensive).

    Also you can wait for the Task to be completed if you need to.
     
  9. truesoldersprit

    truesoldersprit

    Joined:
    Aug 23, 2013
    Posts:
    10
    :DThank you for your kind suggestion
    Ok,I'll try it,
    But I'm wondering it will be run with the all other functions at the same time.
    I'm sure about the thread because it runs with the all other functions at the same time with scheduling method.
    But I'm not sure about the task, if it will be run as a thread, or not.

    How do you think about this?
    I'm a little programmer.
    Please teach me If it doesn't bother you.
    I'm investigating your sample in your Asset Version of UnityThreadHelper.
    Sorry to bother you.
     
    Last edited: Aug 25, 2013
  10. Marrrk

    Marrrk

    Joined:
    Mar 21, 2011
    Posts:
    1,032
    Hi there, the TaskDistributor will create CPU Cores * 2 Threads on which the Tasks you Dispatch will run, so you will at least run the tasks not on the mainthread.
     
  11. truesoldersprit

    truesoldersprit

    Joined:
    Aug 23, 2013
    Posts:
    10
    Thank you!
    Your functions are very good.

    But my program is very unwanted as I want.
    Maybe I have designed algorithm wrong.

    Anyhow Thanks again about your sincere help.

    I'll prepare a question clearly for you.
    If I have problems, I'll ask to you at anytime.
    Is It OK?
     
    Last edited: Aug 26, 2013
  12. Marrrk

    Marrrk

    Joined:
    Mar 21, 2011
    Posts:
    1,032
    Sure, ask ahead.
     
  13. truesoldersprit

    truesoldersprit

    Joined:
    Aug 23, 2013
    Posts:
    10
    Hi, Marrrk.
    I'm using your Asset.

    It is running well on player on Unity.
    But It isn't compiled into Android and IOS version.

    My Error is follow.
    ------------------------------------------------
    Cross compilation job UnityThreadHelper.ThreadSafe.dll failed.
    UnityEngine.UnityException: Failed AOT cross compiler:/Applications/Unity/Unity.app/Contents/BuildTargetTools/iPhonePlayer/mono-xcompiler --aot=full,asmonly,nodebug,static,outfile="UnityThreadHelper.ThreadSafe.dll.s"

    Error building Player:UnityException:Cross compilation failed.
    ---------------------------------------------------
    Please help me.
     
  14. Marrrk

    Marrrk

    Joined:
    Mar 21, 2011
    Posts:
    1,032
    Hi there, iOS prevents JIT compilation, which makes the ThreadSafe dll useless in this case, but you can easy replicate what the dll does by using the dispatcher to transfer calls onto the Main/UI Thread.
     
  15. truesoldersprit

    truesoldersprit

    Joined:
    Aug 23, 2013
    Posts:
    10
    Thanks.

    I can't understand about IOS. I'll review it late
    But I'm needed in Android right now.

    How about Android?
     
  16. Marrrk

    Marrrk

    Joined:
    Mar 21, 2011
    Posts:
    1,032
    Iam not sure wether Android uses an AOT compiler, but I doubt it, so, this will work with Android. But to be on the safe side, dont use the Threadsafe dll stuff.
     
  17. im

    im

    Joined:
    Jan 17, 2013
    Posts:
    1,396
  18. Marrrk

    Marrrk

    Joined:
    Mar 21, 2011
    Posts:
    1,032
    The Version in the assetstore has an additional Assembly which should make the work with the UnityAPI in Threads more easy. which basically wraps every Unity Class and Method into a Dispatch call, you dont need it, also some samples are included.

    Besides this its identical to the version you can find in this thread.

    A have no comparision to loom. But from what I can tell, loom does have some more understandable method names. Something I want too, but I currently lack the time to do this.
     
  19. Fher

    Fher

    Joined:
    Aug 13, 2013
    Posts:
    5
    Hi there!

    I found an incompatibility when a Windows Client (I only tested it in Windows enviroments) is trying to open a Scene with an iGUI Root element and the Thread Helper is loaded.

    To reproduce the error follow the next steps:

    1. Create a new project with a new Scene.
    2. Import iGUI Basic and create the iGUI Root node.
    3. Draw whatever with iGUI Basic.
    4. "Build and Run", you should see your GUI without problems.
    5. Now import the ThreadHelper Package and "Build and Run" again. Your app will crash.

    I need both assets working together, please could you fix it?
    Thanks.
     
  20. Marrrk

    Marrrk

    Joined:
    Mar 21, 2011
    Posts:
    1,032
    I need to look into it. Can you provide me with a log File from the runned build?
     
  21. Fher

    Fher

    Joined:
    Aug 13, 2013
    Posts:
    5
    Here it goes :)

    Initialize engine version: 4.2.1f4 (4d30acc925c2)
    GfxDevice: creating device client; threaded=1
    Direct3D:
    Version: Direct3D 9.0c [nvd3dum.dll 9.18.13.2049]
    Renderer: NVIDIA GeForce GT 440
    Vendor: NVIDIA
    VRAM: 972 MB (via DXGI)
    Caps: Shader=30 DepthRT=1 NativeDepth=1 NativeShadow=1 DF16=0 DF24=0 INTZ=1 RAWZ=0 NULL=1 RESZ=0 SlowINTZ=0
    Begin MonoManager ReloadAssembly
    Platform assembly: E:\Users\Fher\Documents\UnityTest2\test_Data\Managed\UnityEngine.dll (this message is harmless)
    Loading E:\Users\Fher\Documents\UnityTest2\test_Data\Managed\UnityEngine.dll into Unity Child Domain
    Platform assembly: E:\Users\Fher\Documents\UnityTest2\test_Data\Managed\Assembly-CSharp.dll (this message is harmless)
    Loading E:\Users\Fher\Documents\UnityTest2\test_Data\Managed\Assembly-CSharp.dll into Unity Child Domain
    Platform assembly: E:\Users\Fher\Documents\UnityTest2\test_Data\Managed\iGUI.dll (this message is harmless)
    Loading E:\Users\Fher\Documents\UnityTest2\test_Data\Managed\iGUI.dll into Unity Child Domain
    Platform assembly: E:\Users\Fher\Documents\UnityTest2\test_Data\Managed\UnityThreadHelper.dll (this message is harmless)
    Loading E:\Users\Fher\Documents\UnityTest2\test_Data\Managed\UnityThreadHelper.dll into Unity Child Domain
    Platform assembly: E:\Users\Fher\Documents\UnityTest2\test_Data\Managed\UnityThreadHelper.ThreadSafe.dll (this message is harmless)
    Loading E:\Users\Fher\Documents\UnityTest2\test_Data\Managed\UnityThreadHelper.ThreadSafe.dll into Unity Child Domain
    - Completed reload, in 0.065 seconds
    desktop: 1920x1080 60Hz; virtual: 3840x1080 at 0,0
    <RI> Initializing input.

    <RI> Input initialized.

    Platform assembly: E:\Users\Fher\Documents\UnityTest2\test_Data\Managed\System.Core.dll (this message is harmless)
    The file 'E:/Users/Fher/Documents/UnityTest2/test_Data/sharedassets0.assets' is corrupted! Remove it and launch unity again!
    [Position out of bounds! 787900 > 787896]

    (Filename: Line: 269)

    The file 'E:/Users/Fher/Documents/UnityTest2/test_Data/sharedassets0.assets' is corrupted! Remove it and launch unity again!
    [Position out of bounds! 787900 > 787896]

    (Filename: Line: 276)
     
  22. Marrrk

    Marrrk

    Joined:
    Mar 21, 2011
    Posts:
    1,032
    Do you use the free version provided from the link at the startpost or the sourcecode only? The log says that there are corrupted assets in your build. I looked for the error and found out that this may be the result of a filename collision between scripts:

    Platform assembly: E:\Users\Fher\Documents\UnityTest2\test_Data\Manag ed\System.Core.dll (this message is harmless)
    The file 'E:/Users/Fher/Documents/UnityTest2/test_Data/sharedassets0.assets' is corrupted! Remove it and launch unity again!
    [Position out of bounds! 787900 > 787896]

    (Filename: Line: 269)

    The file 'E:/Users/Fher/Documents/UnityTest2/test_Data/sharedassets0.assets' is corrupted! Remove it and launch unity again!
    [Position out of bounds! 787900 > 787896]

    http://forum.unity3d.com/threads/11...-corrupted!-Remove-it-and-launch-unity-again!
    http://answers.unity3d.com/questions/368456/corrupted-maindata.html
     
  23. Fher

    Fher

    Joined:
    Aug 13, 2013
    Posts:
    5
    Hi there!

    I bought the Asset Store version and I directly installed from there.
    Shall I remove some file of the installed ones?
     
  24. Marrrk

    Marrrk

    Joined:
    Mar 21, 2011
    Posts:
    1,032
    I am not sure, I guess you can only rename or change files from iGUI as the AssetStore version is provided as a set of assemblies (.dll´s).

    Yout best bet would be to find the files/scripts with similar class/typenames as the UTH is using. The issue seems to be a conflict between both assets.
     
  25. Fher

    Fher

    Joined:
    Aug 13, 2013
    Posts:
    5
    Hello again,

    I discovered that the problems seems to be inside the ThreadSafe extension because If I remove it the .exe works fine.
    Because iGUI is a set of .dll's too I was checking the namespaces with Visual Studio but I couldn't find any coincidence with UTH.

    Can you help me? Maybe if I post a list with the namespaces?

    Thanks a lot for your time.

    Edit: I just realized that I don't need to use the ThreadSafe so I solved the problem by removing the dll, Its a quick patch for now. By the way, I'm glad about buying your component through the Asset Store, you deserve it :)
     
    Last edited: Sep 17, 2013
  26. Giocas

    Giocas

    Joined:
    Oct 15, 2013
    Posts:
    2
    Hi all,
    hope to post something useful to all.
    Just discovered a little bug on this fantastic code.

    I used the Unity Threading Helper on a scene that is created by the user by clicking on a button. The scene can be destroyed using a back button. The user can than recreate the same scene re-clicking on the first button.
    In this case the code for the singleton in the UnityThreadHelper class doesn't work correctly since the test "null == (object)instance" returns FALSE.
    The problem lies in the "OnDestroy" method that doen't set to null the "instance" variable.
    The solution is simply adding the following line of code:
    instance = null;

    as last line of the OnDestroy() method at line 244 of the UnityThreadHelper
    class file.

    My 2 cents.
     
  27. Marrrk

    Marrrk

    Joined:
    Mar 21, 2011
    Posts:
    1,032
    Hi there, I quickly checked the source (from the start post), and OnDestroy does already set instance to null. Do you have the current version? I can also check the asset store version, but it should be almost equal.

    Greetings, Mark
     
  28. Sleaker

    Sleaker

    Joined:
    Oct 20, 2013
    Posts:
    2
    I recently started doing some things in the editor that make calls to the task dispatcher, as soon as I started doing this it broke all of the threading, now my project wont even run, and it seems the UnityThreadHelper.TaskDistributor is always null. I've tried calling the EnsureHelper method to make sure it's setup, but this doesn't seem to create instances of the TaskDistributor. Any thoughts on how to fix this?
     
  29. Marrrk

    Marrrk

    Joined:
    Mar 21, 2011
    Posts:
    1,032
    If you want to make the UTH work in the editor, try to not use the UnityThreadHelper class, instead of that you can copy the needed functionality of it into a custom class. The UnityThreadHelper class was not made to work in edit time, but everything else should work, once set up.
     
  30. Sleaker

    Sleaker

    Joined:
    Oct 20, 2013
    Posts:
    2

    Ahh this makes sense, I'll probably just try and add something in that checks if it's in editor mode or not, thanks. I did get it so it was kind of working, it just has problems generating things in editor mode, when it goes to swap into game mode it fails. haha.
     
  31. MythicalCity

    MythicalCity

    Joined:
    Feb 10, 2011
    Posts:
    414
    Hi, just testing out the free version and it doesn't seem to work on iOS build. Everything works fine in the Editor but once I build to iOS it just seems to ignore the call:

    UnityThreadHelper.Dispatcher.Dispatch(() => MyFunciton());

    And just tries to load MyFunction directly. Is the free version not compatible with iOS builds that have stripping?

    -JJ
     
  32. Marrrk

    Marrrk

    Joined:
    Mar 21, 2011
    Posts:
    1,032
    Do you call the Dispatch function from the main thread? Or from a custom thread?
     
  33. LostPanda

    LostPanda

    Joined:
    Apr 5, 2013
    Posts:
    168
    Hello,marrrk.I used your Threading Helper.Can you tell me how to MulitThreading load and Unload Asset.Thank you very much!
     
  34. capbob

    capbob

    Joined:
    Nov 18, 2013
    Posts:
    1
    Great asset! It's been a huge help to my project so far.
     
  35. Marionette

    Marionette

    Joined:
    Feb 3, 2013
    Posts:
    349
    Marrrk! excellent asset, just picked it up ;)

    so.. quick question.. is there any way to add or mimic this behavior: .ContinueWhenAll(tasks, finishedTasks => with your asset?

    and if so, how?
     
  36. Marrrk

    Marrrk

    Joined:
    Mar 21, 2011
    Posts:
    1,032
    @LostPanda:
    You will need to load/process as much as possible in a seperate thread and then transfer control to the main thread so that
    you may be able to generate Unity resources out of the processed/loaded data.

    @Marionette:

    I updated the start post of this thread which includes now the latest version with many extensions and improvements.

    Go like channels:
    Code (csharp):
    1.  
    2. var channel = new Channel<bool>();
    3.  
    4. Task.Create(() =>
    5.   {
    6.     Debug.Log("Background: Start.");
    7.     channel.Get();
    8.     Debug.Log("Background: End.");
    9.   }).Run();
    10.  
    11. Debug.Log("MainThread: Start.");
    12.  
    13. channel.Set(true);
    14.  
    15. Debug.Log("MainThread: End.");
    16.  
    Wait for the completion of many tasks:
    Code (csharp):
    1.  
    2. void IEnumerable<TaskBase>.WaitAll();
    3.  
    4. var tasks = new TaskBase[]
    5. {
    6.    Task.Create(() => Debug.Log("Test 1")).Run(),
    7.    Task.Create(() => Debug.Log("Test 2")).Run(),
    8.    Task.Create(() => Debug.Log("Test 3")).Run()
    9. }
    10. tasks.WaitAll();
    11.  
    Do something when every task in a list of tasks has ended:
    Code (csharp):
    1.  
    2. IEnumerable<TaskBase> IEnumerable<TaskBase>.ContinueWhenAllEnded(Action action);
    3. IEnumerable<TaskBase> IEnumerable<TaskBase>.ContinueWhenAllEnded(Action<IEnumerable<TaskBase>> action);
    4.  
    5. var tasks = new TaskBase[]
    6. {
    7.    Task.Create(() => Debug.Log("Test 1")).Run(),
    8.    Task.Create(() => Debug.Log("Test 2")).Run(),
    9.    Task.Create(() => Debug.Log("Test 3")).Run()
    10. }
    11.  
    12. tasks.ContinueWhenAllEnded(() => Debug.Log("Done"));
    13.  
    Do something when one single task in a list of tasks has ended:
    Code (csharp):
    1.  
    2. IEnumerable<TaskBase> IEnumerable<TaskBase>.ContinueWhenAnyEnded(Action action);
    3. IEnumerable<TaskBase> IEnumerable<TaskBase>.ContinueWhenAnyEnded(Action<IEnumerable<TaskBase>> action);
    4.  
    5. var tasks = new TaskBase[]
    6. {
    7.    Task.Create(() => Debug.Log("Test 1")).Run(),
    8.    Task.Create(() => Debug.Log("Test 2")).Run(),
    9.    Task.Create(() => Debug.Log("Test 3")).Run()
    10. }
    11.  
    12. tasks.ContinueWhenAnyEnded(() => Debug.Log("Done"));
    13.  
    Do something when a task has been successfully finished:
    Code (csharp):
    1.  
    2. TaskBase TaskBase.WhenSucceeded(Action action);
    3. TaskBase TaskBase.WhenSucceeded(Action<TaskBase> action);
    4. TaskBase TaskBase.WhenSucceeded(Action<TaskBase> action, Dispatcher target);
    5.  
    6. Task.Create(() => Debug.Log("Test"))
    7.   .Run()
    8.   .WhenSucceeded(() => Debug.Log("Success"));
    9.  
    Do something when a task has been failed/aborted:
    Code (csharp):
    1.  
    2. TaskBase TaskBase.WhenFailed(Action action);
    3. TaskBase TaskBase.WhenFailed(Action<TaskBase> action);
    4. TaskBase TaskBase.WhenFailed(Action<TaskBase> action, Dispatcher target);
    5.  
    6. Task.Create(() => Debug.Log("Test"))
    7.   .Run()
    8.   .WhenFailed(() => Debug.Log("Fail"));
    9.  
    Do something when a task has ended:
    Code (csharp):
    1.  
    2. TaskBase TaskBase.WhenEnded(Action action);
    3. TaskBase TaskBase.WhenEnded(Action<TaskBase> action);
    4. TaskBase TaskBase.WhenEnded(Action<TaskBase> action, Dispatcher target);
    5.  
    6. Task.Create(() => Debug.Log("Test"))
    7.   .Run()
    8.   .WhenEnded(() => Debug.Log("Ended"));
    9.  
    Run an Enumerator at a background thread.
    Code (csharp):
    1.  
    2. TaskBase IEnumerator.Run();
    3. TaskBase IEnumerator.Run(TaskDistributor target);
    4.  
    5. IEnumerator Test()
    6. {
    7.   DoSomethingSlow();
    8.  
    9.   yield SwitchTo.MainThread;
    10.  
    11.   Debug.Log("MainThread!")
    12.  
    13.   yield SwitchTo.Thread;
    14.  
    15.   Debug.Log("Back to work")
    16.   DoSomethingSlow();
    17. }
    18.  
    19. Test().Run();
    20.  
    Runs an action or function at a background thread:
    Code (csharp):
    1.  
    2. Task Action.Run();
    3. Task Action.Run(TaskDistributor target);
    4. Task<T> Func<T>.Run();
    5. Task<T> Func<T>.Run(TaskDistributor target);
    6.  
    7. Task.Create(() => Debug.Log("Test")).Run();
    8.  
    Runs a task after the current one has been successfully finished:
    Code (csharp):
    1.  
    2. TaskBase TaskBase.Then(TaskBase other);
    3.  
    4. var a = Task.Create(() => Debug.Log("A"));
    5. var b = Task.Create(() => Debug.Log("B"));
    6.  
    7. a.Then(B).Run();
    8.  
    Let the current task wait until the other task has been successfully finished:
    Code (csharp):
    1.  
    2. TaskBase TaskBase.Await(TaskBase other);
    3.  
    4. var a = Task.Create(() => Debug.Log("A"));
    5. var b = Task.Create(() => Debug.Log("B"));
    6.  
    7. b.Await(a);
    8. a.Run();
    9.  
     
  37. Marionette

    Marionette

    Joined:
    Feb 3, 2013
    Posts:
    349
    excellent, thank you ;)

    has this been updated already and do I need to get a new version or is it already in the version I got when I bought it a day ago?
     
    Last edited: Jan 21, 2014
  38. Marrrk

    Marrrk

    Joined:
    Mar 21, 2011
    Posts:
    1,032
    I issued an update right now, version 1.5 it may be only at the end of the week or next week.

    But you can still grab the version from the start post of this thread. It doesnt include the sample scene, but you may not need it to use the new stuff.

    Beginning with the 1.5 version there are also some serious changes:
    TaskBase is gone, the main base class of all Tasks is Task
    The ThreadSafe namespace and all things included in it are gone too. It did hide many functions, made things not better readable and it wont work on mobile devices, so I removed it for now.

    Also I fixed many issues, added the events and added many extension methods.

    You all can read about that in the API reference (http://dras.biz/download/UnityThreadHelper/Help/Index.html) have a look at the new Extensions.
     
  39. Groszq

    Groszq

    Joined:
    Sep 20, 2012
    Posts:
    4
    Hello There,

    I haven't found pure answer to my question so I will write it down.
    Is it possible with that asset to load asynchronously Texture2D from resources, without using MainThread of Unity?

    Thank you in advance,

    Alex "Groszq"
     
  40. Alesk

    Alesk

    Joined:
    Jul 15, 2010
    Posts:
    337
    Hi,

    Little question about mobile platforms : the threading helper is perfectly working on my computer, but slower on Android (at least on my current test, with a 4 cores device), and my app become faster when I disable the helper and do everything on the main thread.

    Is this normal ?
     
  41. Marionette

    Marionette

    Joined:
    Feb 3, 2013
    Posts:
    349
    Hey Marrrk?

    I have a scenario where I'd like to spin up n number of threads that process a central queue, but remain running, they don't die after their work. We'll say 8 threads for sake of argument. As I push something onto the queue, the first thread available grabs it and starts processing it. In the meantime, there are other items being pushed into the queue that I want a subsequent available thread to pick up the item and process etc up to the limit of the threads, in this case 8.

    I'm basically trying to figure out the best way to create a round robin threading scheme using your asset. I tried using the online help you have, but nothing displays except the menu on the left. For some reason I can't see anything on the right. I looked at the examples you gave above, but I'm a little confused as to which would be the best in the scenario I laid out above. This has to have as little impact on the main thread as absolutely possible.

    Is there any way I might beg a small snippet from you that might point me in the right direction?

    Am I to use the TaskDistributor and add tasks that way? And my question then becomes, if I specify the number of threads in the constructor, will it handle maintaining those threads or do I need to keep them alive?

    hehe I'm sure I can ultimately figure this out, I'm just hoping to get a small leg up.

    thanks! ;)
     
  42. Marionette

    Marionette

    Joined:
    Feb 3, 2013
    Posts:
    349
    btw, I got the help to work. needed to use compatibility mode?
     
  43. Marionette

    Marionette

    Joined:
    Feb 3, 2013
    Posts:
    349
    starting to get a little frustrated..
     
  44. Marrrk

    Marrrk

    Joined:
    Mar 21, 2011
    Posts:
    1,032
    @Marionette: You are right with the TaskDistributor. When creating it you can specify the number of worker threads the distributor will use internally. The default value is zero which means that the TD will create 2 * system cores worker threads.

    The TaskDistributor will manage the threads and you dont have to worry about their lifetime. You can push Tasks into the TD by either calling the Dispatch method directly on the TD or by providing the TD in the Run method of any task created.

    Once you are finished using the TD you must call the Dispose method which will shutdown the worker threads, do this when the App will shutdown or a special gameObject which holds the TD will be destroyed.

    The TD will distribute all qued tasks evenly on the waiting worker threads. The worker threads will do nothing until they receive a task, which means that no CPU time will be wasted.
     
  45. Marrrk

    Marrrk

    Joined:
    Mar 21, 2011
    Posts:
    1,032
    @Groszq:

    You can load the raw data in any thread, as long as you DO NOT use any Unity API calls, you can use the normal .Net/Mono API for this. The creation and filling of the Unity resource (Texture2D) MUST be dispatched onto the mainthread.

    @Alesk: Thats strange, could you show me what you are doing in the threadsand how you use the UTH?
     
  46. Marionette

    Marionette

    Joined:
    Feb 3, 2013
    Posts:
    349
    that's what I thought, however the behavior is different.

    if I have 20 tasks in the queue, and 8 threads spun up, i'd expect the taskcount to decrement by 8, until there are less than 8 etc..

    what's happening now, using your example scene, is that I create a new task distributor with 8 threads. I do not set it to auto start. I add 20 tasks. then call the distributor.start() method.

    the first 8 tasks fire off as expected, then all threads end except 1, which processes the queue 1 at a time. I checked this by checking the isalive status of each thread as well as the task count.

    I also added a thread/task id to each thread so I could see what was going on..
     
  47. Marionette

    Marionette

    Joined:
    Feb 3, 2013
    Posts:
    349
    I create a distributor when the class is created thusly:

    Code (csharp):
    1. TaskDistributor _distributor = new TaskDistributor("TestDistributor", 8, false);
    then when the button for the task distributor is clicked:

    Code (csharp):
    1. for (int t = 0; t < 20; t++)
    2.             {
    3.                 _distributor.Dispatch(() =>
    4.                     {
    5.                         //Interlocked.Increment(ref currentTask);
    6.  
    7.                         int[][] arrays = null; arrays = new int[1000][];
    8.                         for (int i = 0; i < arrays.Length; ++i)
    9.                         {
    10.                             arrays[i] = new int[10000];
    11.                             for (int k = 0; k < arrays[i].Length; ++k)
    12.                             {
    13.                                 arrays[i][k] = random.Next(10000);
    14.                             }
    15.                         }
    16.  
    17.                         return arrays;
    18.  
    19.                     }).WhenEnded((a) =>
    20.                         {
    21.                             ProcessArrays(t, a.Result);
    22.                            
    23.                         });
    24.             }
    25.  
    26.             _distributor.Start();
    after the arrays are created the WhenEnded calls the ProcessArrays method passing in the 'taskid' along with the processed array:

    Code (csharp):
    1. private void ProcessArrays(int taskID, int[][] arrays)
    2.     {
    3.         for (int i = 0; i < arrays.Length; ++i)
    4.         {
    5.             var index = i;
    6.  
    7.             //_distributor.Dispatch(() =>
    8.             //{
    9.                 System.Array.Sort(arrays[index]);
    10.                 System.Threading.Interlocked.Increment(ref sortedArrays);
    11.  
    12.                 currentTask = taskID;
    13.  
    14.                 if (sortedArrays == arrays.Length)
    15.                 {
    16.                     isCalculating = false;
    17.                     sortedArrays = 0;
    18.                 }
    19.             //});
    20.         }
    21.     }
     
  48. Marionette

    Marionette

    Joined:
    Feb 3, 2013
    Posts:
    349
    the more I delve into this, the more interesting results i'm getting back..
     
  49. Marrrk

    Marrrk

    Joined:
    Mar 21, 2011
    Posts:
    1,032
    Please keep in mind that you need to create a temp variable in your for (int t ...) loop of the t variable himself and then use this tmp Variable inside your task. If you dont do this, then your tasks will use the last state of t, which will be 20. This is called variable hoisting if I am correct.


    I checked the TD with your code, every TaskWorker has always something to do. I cant spot any errors/problems.

    Also: WhenEnded will be called on the current working Thread, which means that you basically enhance your Task when not providing an other task distributor/dispatcher.
     
  50. Marionette

    Marionette

    Joined:
    Feb 3, 2013
    Posts:
    349
    as soon as I can get some video capture stuff available, i'll post.. and yes, I knew about the hoisting.. that was left over from some other tests I was doing etc..