Search Unity

[50USD] Easy threading - Multi threading made easy!

Discussion in 'Assets and Asset Store' started by arklay_corp, Aug 18, 2014.

  1. piotrO

    piotrO

    Joined:
    Dec 16, 2009
    Posts:
    46
    Hi Arklay,

    Unfortunately the Wait function used without any arguments isn't working.

    For blocking wait I use this piece of code:

    Code (CSharp):
    1. Task t1 = Task.Run(()=>{
    2.   Task tm1 = Task.RunInMainThread(() => { DoUnityStuff(); });
    3.  
    4.         while (!tm1.IsCompleted) Task.Delay(10);
    5. });
    6.  
    Could you tell me is it safe to use it like this?
     
    Last edited: Apr 7, 2018
  2. arklay_corp

    arklay_corp

    Joined:
    Apr 23, 2014
    Posts:
    242
    It is safe, not what i would recommend but its safe (at least you are not blocking the main thread)
     
  3. zhao_KK

    zhao_KK

    Joined:
    Jun 7, 2017
    Posts:
    11
    Great plugin
    But I have a problem. If I want to load a large Ogg file locally and www does not support threads, how do I use this plugin?
     
  4. arklay_corp

    arklay_corp

    Joined:
    Apr 23, 2014
    Posts:
    242
    you could use this plugin and download it on a background thread using net classes, raw sockets... anything you want.

    but www does uses background threads as long as you use
    Code (CSharp):
    1. yield return www;
    the download is done on a secondary thread and when it finished the execution goes back to the main thread in the corutine
     
  5. madbeagle

    madbeagle

    Joined:
    Jan 16, 2014
    Posts:
    10
    Hi, really like this product and making extensive use of it, but have a weird issue in Unity 2018.1.

    Any runtime errors that occur anywhere downstream on a .ContinueInMainThreadWith() call are not being reported in the console. If I wrap the same code in a coroutine instead and call the continuation method manually, I get the expected runtime errors.

    This is making debugging tricky to say the least!
     
  6. arklay_corp

    arklay_corp

    Joined:
    Apr 23, 2014
    Posts:
    242
    Yeah, thats a big problem, but is not related with easy threading, Unity doesn't show Exceptions being thrown in a thread different than the main one, my advice would be to try catch them all and log them via Debug.LogException
     
  7. madbeagle

    madbeagle

    Joined:
    Jan 16, 2014
    Posts:
    10
    But shouldn't this code be running in the main thread? It's in a method called by .ContinueInMainThreadWith() - and any further methods called as a result.

    It accesses Unity APIs, playerprefs, instantiates GameObjects etc. without a problem, but if there is a runtime error such as null exceptions, I get nothing in the log.
     
  8. arklay_corp

    arklay_corp

    Joined:
    Apr 23, 2014
    Posts:
    242
    but it is launched via an action, i think that messes up unity's console
     
  9. mmvlad

    mmvlad

    Joined:
    Dec 31, 2014
    Posts:
    98
    Hi @arklay_corp
    your website is down so I can't access docs.
     
  10. Quatum1000

    Quatum1000

    Joined:
    Oct 5, 2014
    Posts:
    889
    Perhaps he decide to depreciate the asset, because of the unity job system.
     
  11. arklay_corp

    arklay_corp

    Joined:
    Apr 23, 2014
    Posts:
    242
    hi,

    @Quatum1000 is almost right, I'm just giving support to this plugin but it won't be updated because unity 2018.2 already implements the actual proper native Task management system (thank god). I will just give support for people (including me) stuck in old unity versions (bug fixing and so on), but makes no real sense to expand this plugin further.

    About the website, I had some problems with my hosting provider. Anyway whole documentation can be found in the package and here (and I'm around if you have questions)
     
  12. mmvlad

    mmvlad

    Joined:
    Dec 31, 2014
    Posts:
    98
  13. inod_clement

    inod_clement

    Joined:
    Nov 9, 2016
    Posts:
    17
    Hi,

    I just bought your asset for import several pictures.
    I try your proposition but it's impossible to find a solution. i tried this:

    Code (CSharp):
    1.  
    2.   void Start()
    3.     {
    4.         textureList = new List<Texture2D>();
    5.         DirectoryInfo direct = new DirectoryInfo(rootPath);
    6.         info = direct.GetFiles("*.*", SearchOption.AllDirectories).Where(f => extensions.Contains(f.Extension.ToLower())).ToArray();
    7.         for (int i = 0; i < info.Length; i++)
    8.         {
    9.             pathFile = @info[i].FullName;
    10.  
    11.             Task<byte[]>.Run(() => GetTexture(pathFile)).ContinueInMainThreadWith(taskResult =>
    12.             {
    13.                 if (taskResult.IsFaulted)
    14.                 {
    15.                     Debug.LogException(taskResult.Exception, this);
    16.                 }
    17.                 else
    18.                 {
    19.                     Texture2D tex = new Texture2D(1, 1);
    20.                     tex.LoadRawTextureData(taskResult.Result);
    21.                     tex.name = Path.GetFileNameWithoutExtension(@info[i].Name);
    22.                     textureList.Add(tex);
    23.                 }
    24.             });
    25.  
    26.         }
    27.     }
    28.     public byte[] GetTexture(string p)
    29.     {
    30.         byte[] textureData = null;
    31.         textureData = File.ReadAllBytes(p);
    32.         return textureData;
    33.     }
    34.  
    Do you have an idea ?

    Thanks
     
    chambino likes this.
  14. yangkairong

    yangkairong

    Joined:
    Aug 20, 2015
    Posts:
    16
    I'd like to have the following functionality, because it's very difficult for a sub-thread to get some data from the main thread. Here's just pseudo-code.
    Code (CSharp):
    1. //
    2.             Task.Run(() => {          
    3.                 // When this function is called, the child thread will wait for the main thread's data to return safely.
    4.                 byte[] bytes = Dispatcher.DispatchToMainThreadReturn(() =>
    5.                 {
    6.                     // WWW class objects can only be used in the main thread, but my child thread needs to use the data in WWW.
    7.                     return www.bytes;
    8.                 }, true) as byte[];
    9.             })          
    10.         }
     
  15. yangkairong

    yangkairong

    Joined:
    Aug 20, 2015
    Posts:
    16
    The Android platform at unity 2018.2.3 didn't work very well.
    Code (CSharp):
    1.  Task.Run(() =>
    2. {
    3.           // sub thread workload      
    4. })
    5. .ContinueInMainThreadWith((t) =>
    6. {                      
    7.            // main thread sometimes there is no work.
    8. }
    Please repair this bug.
     
  16. freakyuito

    freakyuito

    Joined:
    Sep 18, 2018
    Posts:
    1
    Hi Arklay,I am confuse about this code,I want to use unitywebrequest to aquire some data but unity report error like this:
    upload_2018-11-14_22-59-48.png
    the source code is here:
    upload_2018-11-14_22-55-54.png
    could u plz help me :)
     
  17. arklay_corp

    arklay_corp

    Joined:
    Apr 23, 2014
    Posts:
    242
    UnityWebRequest needs to run in the main thread, you cannot use Task.Run there
     
  18. Roni92pl

    Roni92pl

    Joined:
    Jun 2, 2015
    Posts:
    396
    Yeah, WebRequest is done in background thread anyway.
     
  19. justtime

    justtime

    Joined:
    Oct 6, 2013
    Posts:
    424
    Is it ok use Task.Run inside of Unity Coroutine ?
     
  20. arklay_corp

    arklay_corp

    Joined:
    Apr 23, 2014
    Posts:
    242
    Yes, it is ok
     
    justtime likes this.
  21. justtime

    justtime

    Joined:
    Oct 6, 2013
    Posts:
    424
  22. arklay_corp

    arklay_corp

    Joined:
    Apr 23, 2014
    Posts:
    242
    You can use any c# synchronization tools (semaphores would be a good choice for waiting for a couroutine to finish)
     
  23. gamebytom

    gamebytom

    Joined:
    Mar 13, 2017
    Posts:
    10
    Like inod_clement in the post above, I want to load textures asynchronously. I tried your code but couldn't get it working. Could you send me a full working example of async texture loading? Just to a canvas from an example image file. You could also add the example to your asset - this is a common problem according to the Internet research I've done on this so I think a lot of people would find it helpful.
     
  24. arklay_corp

    arklay_corp

    Joined:
    Apr 23, 2014
    Posts:
    242
    You can load the image from disk to memory (into a byte array) on a secondary thread, you could even decode it to ARGB to make unity's work easier. But creating the actual texture needs to be done in the main thread (that's a unity limitation)

    Easy threading gives you tools for everything you need, launching the thread to read the file. an sending the execution back to main thread to create the texture
     
  25. gamebytom

    gamebytom

    Joined:
    Mar 13, 2017
    Posts:
    10
    Thanks for getting back to me. I guess I need to use Task.RunInMainThread(SomeFunction); - if it's running in the main thread is it still in parallel? Does it work across frames like coroutines?
     
  26. arklay_corp

    arklay_corp

    Joined:
    Apr 23, 2014
    Posts:
    242
    U need to launch a background task (Task.Run) to perform all the tasks you can do in a background thread (open the image file, read it to memory and optionally decode it to RGBA), once this is done U need to send execution back to main thread (Task.RunInMainThread) to create the Texture2D object

    If it is running in the main thread it is not running in parallel. Coroutines always run in the main thread, unity is (mostly) single-threaded
     
    justtime likes this.
  27. justtime

    justtime

    Joined:
    Oct 6, 2013
    Posts:
    424
    Hi there! I call Task.Run, inside if it, call Task.RunInMainThread, can i somehow wait for ending of this RunInMainThread and continue threaded calculations?
    Wait on RunInMainThread taks not working.
     
    Last edited: Oct 16, 2019
  28. arklay_corp

    arklay_corp

    Joined:
    Apr 23, 2014
    Posts:
    242
    You could use
    Code (CSharp):
    1. RunInMainThread (SomeWorkInMainThread).ContinueWith(SomeWorkInBackgrounThread)
     
  29. justtime

    justtime

    Joined:
    Oct 6, 2013
    Posts:
    424
    For me in this case SomeWorkInBackgrounThread works in Main thread.
     
  30. arklay_corp

    arklay_corp

    Joined:
    Apr 23, 2014
    Posts:
    242
    Maybe change it to:
    Code (CSharp):
    1. RunInMainThread (SomeWorkInMainThread).ContinueWith(() => Task.Run(SomeWorkInBackgrounThread))
    2.  
    To ensure it runs in a background thread
     
    justtime likes this.
  31. justtime

    justtime

    Joined:
    Oct 6, 2013
    Posts:
    424
    I found solution in this forum
    Code (CSharp):
    1. prepareTrackDownloadProc = Task.RunInMainThread(() => {
    2.                              
    3.                                 }
    4.                             });
    5.  
    6.                             prepareTrackDownloadProc.Wait((_) => mre.Set());
    7.                             mre.WaitOne();
    Strange, that without mre it's not working(not waiting).
     
  32. justtime

    justtime

    Joined:
    Oct 6, 2013
    Posts:
    424
    Hi there! Is it save to call Task.Run() method inside the awaitable Coroutine?
    This works, but I am afraid that this may lead to a failure.

    Also, did i abort thread right to ensure that only 1 thread at a time can do my method?
    Code (CSharp):
    1. if (_playTrackTask != null && !_playTrackTask.IsAborted && !_playTrackTask.IsCompleted)
    2.                     _playTrackTask.AbortThread();
    In example thread continue to execute current method while aborting, and just after delay aborts. Can i immediately abort thread?
     
    Last edited: Oct 23, 2019
  33. justtime

    justtime

    Joined:
    Oct 6, 2013
    Posts:
    424
    It's not related to previous post, but seems that this is not correct behavior on "Wait for group of threads" button click


    Where is 2/7, they are two 3/7. Or is it ok?
     
  34. arklay_corp

    arklay_corp

    Joined:
    Apr 23, 2014
    Posts:
    242
    The threads can not be aborted in Mono, you need to use a CancelationToken and check it in your code
     
    justtime likes this.
  35. arklay_corp

    arklay_corp

    Joined:
    Apr 23, 2014
    Posts:
    242
    Unity console is a bit faulty while multithreading, thats why the example logs to the yellow text box. If you debug the code you will see all tasks are executed properly
     
    justtime likes this.
  36. justtime

    justtime

    Joined:
    Oct 6, 2013
    Posts:
    424
    Does TaskCompletionSource suitable for this purpose,c(an't understand what is TaskCompletionSource for)?
     
  37. arklay_corp

    arklay_corp

    Joined:
    Apr 23, 2014
    Posts:
    242
    TaskCompletionSource allows you to control and pass around TaskCompletionToken to mark the progress and result of a Task (a google search will bring a lot of documentation)

    CancellationTokenSource is similar but a bit different it allows you to pass a CancelationToken to a task to be able to cancel it.

    If you are not familiar with either, I suggest you a fast and dirty solution that would be to pass a bool variable to the Task named "cancelRequested" and initialized to False.

    From outside the task if you need to cancel it you would just set it to True.

    From inside the task you would check the value of the bool variable and, in case it is set to true, just raise a CancellationException, that you would be able to recognize on the task return (in the continuation action)
     
  38. abcppuu

    abcppuu

    Joined:
    Dec 30, 2016
    Posts:
    1
    I just purchased this Assets, but the documentation website is down. Is there anywhere else I can find the documentation? Thanks.
     
  39. arklay_corp

    arklay_corp

    Joined:
    Apr 23, 2014
    Posts:
    242
    In the first pages of this thread you can find the general information, if you need extra help I'm always around
     
    AlanMattano likes this.
  40. ccoutinho

    ccoutinho

    Joined:
    Dec 24, 2016
    Posts:
    20
    Hi - I would like to purchase this asset, but am not sure if its being supported still as the last update was in 2017. Kindly advise so I may purchase.
     
  41. arklay_corp

    arklay_corp

    Joined:
    Apr 23, 2014
    Posts:
    242
    Hi @ccoutinho , you don't need this package for 2017, you have Tasks natively implemented in .NET 4

    If something you will need a method to bring the execution flow back to the main thread. Let me know if you need the code for it, and I will gladly post it here
     
  42. Nameless777

    Nameless777

    Joined:
    Jan 4, 2019
    Posts:
    4
    well i am very noob to multithreading.so i just found some solution and this is the best solution for me i just write one line
    Task.Run(Something) and walla that function runs in other thread.i really love this.
    but now i have a problem and that is let me first show my code.

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. using U3D.Threading.Tasks;
    5. using SA.Android.Contacts;
    6. public class Test : MonoBehaviour
    7. {
    8.     public void Run_ContactThread()
    9.     {
    10.             Task.Run(Get_Contacts());
    11.     }
    12.     public void Get_Contacts()
    13.     {
    14.         AN_ContactsContract.Retrieve((result) =>
    15.         {
    16.             if (result.IsFailed)
    17.             {
    18.                 Debug.Log("Filed:  " + result.Error.Message);
    19.                 return;
    20.             }
    21.  
    22.             Debug.Log("Loaded: " + result.Contacts.Count + " Contacts.");
    23.             foreach (var contact in result.Contacts)
    24.             {
    25.                 // var view = Instantiate(m_contactView.gameObject).GetComponent<AN_ContactsEampleView>();
    26.                 // view.transform.SetParent(m_contactView.transform.parent);
    27.                 // view.gameObject.SetActive(true);
    28.                 // view.SetContactInfo(contact);
    29.                 print(contact.Phone + "\n");
    30.             }
    31.         });
    32.     }
    33. }
    in above code i use Android Native Pro For Fetching User device's contacts and print all those contacts in console.
    so previously(before usign this plugin) i have a button and when i push that button after 30 to 35 sec(depending on User contacts) all contacts are appear in console(well i use mobile console for this).so basically it takes 30 to 35 sec to load all contacts.so for 30 to 35 seconds my whole scene is freez bcz all those processes were worked in main thread.so basically i use this asset for push those calculations in other thread.
    so my problem is that when i try to call Get_Contacts() function in other thread it just won't work.
    and i tried same thing with other function which also take some time to finish and whole scene is freez.but after using this plugin that process run in background and my current scene runs very smoothly.
    so can somebody please help me that how to get rid of this problem.i thought that lambdas not worked with this or somethin else(very confused!!).so please can somebody sugest me something or how can i run "Get_Contacts()" function or i missing something.
    Please help me.
     
  43. arklay_corp

    arklay_corp

    Joined:
    Apr 23, 2014
    Posts:
    242
    It feels like the funtion AN_ContactsContract.Retrieve already runs in its own thread (that's why it needs a callback). As you point out the issue is that function, not the thread creation
     
  44. fisherman_b

    fisherman_b

    Joined:
    Dec 18, 2014
    Posts:
    36
    Hello,

    I have a networking client component that needs to live in a permanet background thread to be able to keep multiple permanent connections to a server to send updates and receive push-style server messages.

    How would I use Easy Threading to create and run such a permanet background thread - from starting to end of the program?
     
  45. arklay_corp

    arklay_corp

    Joined:
    Apr 23, 2014
    Posts:
    242
    No need to use Easy Threading since Unity already has native support for Tasks.

    You can create and run the background thread using
    Task.Run
     
  46. fisherman_b

    fisherman_b

    Joined:
    Dec 18, 2014
    Posts:
    36
    Ok - I thought it can make things easier when it comes to interaction between background thread and main thread (applying values received in background thread to gameobject transforms in main thread etc.)
     
  47. arklay_corp

    arklay_corp

    Joined:
    Apr 23, 2014
    Posts:
    242
    Yes, it does handling sending execution to the main thread, but that's a very basic feature. You can easily implement it by creating a singleton monobehaviour which receives execution requests (eg as an Action object) and just fires them in its Update method
     
  48. fisherman_b

    fisherman_b

    Joined:
    Dec 18, 2014
    Posts:
    36
    Thanks! I guess then I misinterpreted the purpose of this asset.
     
  49. arklay_corp

    arklay_corp

    Joined:
    Apr 23, 2014
    Posts:
    242
    No problem,
    This asset makes sense for unity versions that don't support Tasks natively.