Unity Threading Helper

Unity Threading Helper
583149--36319--$Fotolia_34453816_XS.jpg

Hi there,

for my current Project I have created a little side product and I want to share this little side product with you.

As the thread title already says i, I created something to help me and you when working with Threads and Unity.

AssetStore Version (Contains examples)
The free version (does not contain any examples): 583149–86996–$UnityThreading.zip (17.8 KB)

The API reference

So now the important stuff:

Why do I want to use it?
Because Unity is basically not multi thread compatible and does not provide any helper methods or classes for the work with threads. You can of course create everything you need with Mono, but if you want to just use multi threading you can now.

How do I use it?
Simply import the package. Now you can use inside your scripts the UnityThreadingHelper class. this class provides a bunch of static methods and properties:

  • UnityThreadingHelper.Dispatcher - tell the MainThread to run a bunch of commands (Unity commands for example)
  • UnityThreadingHelper.TaskDistributor - run a bunch of commands in a free worker thread
  • UnityThreadingHelper.CreateThread - create a new thread which runs the given bunch of commands

I will go more in detail in the following questions.

How do I remove it?
The UnityThreadingHelper will automatically remove every thread when leaving the game mode. But if you want manual control over the life time of the created Threads and Tasks you can call Dispose() on almost every class in this package.

How do I create a new thread?
To create a new Thread call one of the 4 versions of UnityThreadHelper.CreateThread:

2 simple examples:

UnityThreading.ActionThread myThread;

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

void DoThreadWork()
{
  // processing
}
UnityThreading.ActionThread myThread;

void Start()
{
  myThread = UnityThreadHelper.CreateThread(() =>
  {
    // processing
  });
}

Which version you prefer is up to you :slight_smile:
You dont even need to store the return value of CreateThread, the UnityThreadHelper will take care of finished threads. But if you want to maybe send an abort signal to the thread processing method you will need to store it.

How do I check inside the thread if the thread should abort, and how do I abort it?
Easy, simply check in your thread function if the ShouldStop property is set to true:

void DoThreadWork(UnityThreading.ActionThread thread)
{
  // processing

  // check if we should stop
  if (thread.ShouldStop)
    return; // finish

  // more processing when we should not stop yet
}

Or:

void DoThreadWork()
 {
   // processing

  // check if we should stop
  if (UnityThreading.ActionThread.CurrentThread.ShouldStop)
    return; // finish

  // more processing when we should not stop yet
 }

And this is how you can signal the thread to stop:

myThread.Exit(); // this signals the thread to stop
myThread.Abort(); // this forces the thread to stop and waits until the thread has stopped.
myThread.AbortWaitForSeconds(10.0f); // this forces the thread to stop and waits max. 10 seconds, when its not stopped after this time, the thread will be terminated

A thread will automatically stop when the thread process function leaves.

How do I call unity commands and methods with it?
When you need to call something at the MainThread you can make use of the Dispatcher, the Dispatcher is a little class which will be updated each frame and will process all commands it has been send from an other thread. The most easy way to send a command or a bunch of commands into the MainThread is this:

 void DoThreadWork()
  {
    // instantiate the asset "enemy"
  UnityThreadHelper.Dispatcher.Dispatch(() => Instantiate(Resources.Load("enemy")));

  // or like this:
  var objectToInstantiate = "enemy";
  UnityThreadHelper.Dispatcher.Dispatch(() => Instantiate(Resources.Load(objectToInstantiate)));

  // or more like this:
  var health = Mathf.Random(10, 100);
  UnityThreadHelper.Dispatcher.Dispatch(() =>
  {
    var newGameObject = Instantiate(Resources.Load(objectToInstantiate));
    newGameObject.GetComponent<MyComponent>().health = health;
  } 
  }

The Dispatch method returns an instance of the Task class, if you want you can use it for example to wait for completion of the dispatched operation:

var task = UnityThreadHelper.Dispatcher.Dispatch(...);
task.Wait();

Also a great feature of the Dispatcher is the ability to dispatch not only methods, but also functions:

var task = UnityThreadHelper.Dispatcher.Dispatch(() => { return 1+1; });
var result = task.Wait<int>();
var task = UnityThreadHelper.Dispatcher.Dispatch(() => { return 1+1; });
task.Wait();
var result  = task.Result;

There are many many more features to discover, just throw a look into what IntelliSense displays for you or ask me :slight_smile:

How do I create simple background Tasks and why not use a extra thread?
If you have many sub operations you dont want to create an extra thread, every thread created will lower the overall performance of the process and will also take some time to be created (noticeable when you create many threads).

Simple background tasks dispatched by the TaskDistributor class will allow a very large amount of tasks to be processed without the need of the creation of many extra threads.

To use the TaskDistributor just call UnityThreadHelper.TaskDistributor and use the instance like a Dispatcher:

UnityThreadHelper.TaskDistributor.Dispatch(...);

It works exactly like the Dispatcher with the difference that every task will be processed in the background. The current implementation of the TaskDistributor allows up to ProcessorCount multiplied by 3 parallel tasks to be operated. Dont worry, if you dispatch more than this amount, the tasks will be processed at the time the amount is below this value.

Questions, comments, encouraging love letters, everything is welcome :slight_smile:

AssetStore Version
Basic version: 583149–86996–$UnityThreading.zip (17.8 KB)

Cool, looks very useful. Does it work the same in unityscript?

I am no UnityScript coder, but it should work there too, the only difference will be the usage of anonymous functions

C#

() =>
{
  // Do something
}

UnityScript

function()
{
  // Do something
}

Someone with more UnityScript experience than me should test this. (I would test it but I am not on a Unity capable system right now).

Hmm looks nice - I will give it a try. Thanks for sharing :slight_smile:

I write a system which allows you to call Unity methods without the need of a Dispatcher call (at least you dont need to call it, under the hood its still done). Tell me what you think.

Example for static methods (unfortunately there are no static extension methods in the current C# version):

using UnityThreadingExtensions
...

void DoThreadWork()
{
    ...
    AssetStoreMT.SaveWait();
    AssetStoreMT.RefreshWait();
}

Sample for instance methods:

using UnityThreadingExtensions
...

void DoThreadWork()
{
    ..
    var myComponent = myGameObject.GetComponentMTWait<MyComponent>();
    myComponent.DoSomethingMT();
    myComponent.DoModeMT();
    myComponent.CalcPiMT();
    myComponent.AngerBadPeopleMT();
}

Basically I extend the unity classes (and also your classes if you run a little helper tool to create the neccessary stuff) about 2 methods for each original method.

Generated sample script:

namespace UnityThreadingExtensions
{
    public static class TestClassMT
    {
        #region StaticMethods

        public static TaskBase StaticTest<T, U>(T a, U b)
        {
            return Dispatcher.Main.Dispatch(() => { TestClass.StaticTest<T, U>(a, b); });
        }

        public static void StaticTestWait<T, U>(T a, U b)
        {
            Dispatcher.Main.Dispatch(() => { TestClass.StaticTest<T, U>(a, b); }).Wait();
        }

        public static TaskBase StaticTest()
        {
            return Dispatcher.Main.Dispatch(() => { TestClass.StaticTest(); });
        }

        public static void StaticTestWait()
        {
            Dispatcher.Main.Dispatch(() => { TestClass.StaticTest(); }).Wait();
        }

        #endregion StaticMethods

        #region Methods

        public static TaskBase GenericTestMT<T>(this TestClass _TestClass, Int32 a)
        {
            return Dispatcher.Main.Dispatch(() => { _TestClass.GenericTest<T>(a); });
        }

        public static T GenericTestMTWait<T>(this TestClass _TestClass, Int32 a)
        {
            return Dispatcher.Main.Dispatch(() => { return _TestClass.GenericTest<T>(a); }).Wait<T>();
        }

        public static TaskBase RefTestMT(this TestClass _TestClass, String a, ref Boolean b)
        {
            return Dispatcher.Main.Dispatch(() => { _TestClass.RefTest(a, ref b); });
        }

        public static void RefTestMTWait(this TestClass _TestClass, String a, ref Boolean b)
        {
            Dispatcher.Main.Dispatch(() => { _TestClass.RefTest(a, ref b); }).Wait();
        }

        public static TaskBase OutTestMT(this TestClass _TestClass, out Boolean a)
        {
            a = default(Boolean);
            return Dispatcher.Main.Dispatch(() => { _TestClass.OutTest(out a); });
        }

        public static void OutTestMTWait(this TestClass _TestClass, out Boolean a)
        {
            a = default(Boolean);
            Dispatcher.Main.Dispatch(() => { _TestClass.OutTest(out a); }).Wait();
        }

        #endregion Methods
    }
}

Original class:

public sealed class TestClass
{
    public static void StaticTest<T, U>(T a, U b) { }
    public static void StaticTest() { }
    public T GenericTest<T>(int a) { return default(T); }
    public void RefTest(string a, ref bool b) {}
    public void OutTest(out bool a) { a = true; }
}

There will be a method with MT as postfix which will not block the calling thread and returns a Task class (see above). Using this would be good in situations in which you want to process these methods without the thread to wait for completion.

And there will be a method with MTWait as postfix, this will block the thread execution until the main thread executed the method. Also MTWait methods will return the return value of the original method so that you can depend other operations on this.

So what do you think?

This seems very very useful… I wish I knew more about threading in general :wink:

Thankfully you’ve provided a good deal of usage examples, so I’ll try later on to integrate that into my project… drawing procedural terrain is no mean task for a single core… and those coroutines are driving me crazy…

Thanks for sharing it with the community!!

Cheers

Oh my, exactly what I was looking for! There’s so many applications for this… Many thanks for sharing this, it would’ve taken me ages to figure out this stuff myself as I’m not really familiar with threading. :slight_smile:

As for the NameMT classes and methods, I’ll have to play around a bit. My first instinct is that I’d rather use the dispatcher calls explicitly, and I don’t like it when my namespaces suddenly get twice as big. But if in use it turns out that explicit dispatcher calls are cumbersome to use then I’d gladly use the MT style.

Thanks for sharing this!

it’s so good to have such an ability in unity !

This is a super handy package - thanks Marrrk!

I’m using it in UnityScript now and it’s working great. As expected with threading, Unity functions break, but they can often be moved or replaced by the .NET equivalent.

A note for UnityScript users on this however:

You’ll need to place the Threading folder the package extracts, into either the Standard Assets, Pro Standard Assets or Plugins folder. Because it’s in C# and we’re using another language to access the namespace, the threading scripts need to be compiled first.

More detail:

and

Once that’s done you can declare the thread variable for use as follows:

var myThread : UnityThreading.ActionThread;

And calling it…

myThread = UnityThreadHelper.CreateThread(myFunction)

Once again, brilliant work Marrrk!

Good to see that its used :smile:

Wow, thanks for sharing this… It looks very useful :smile:

Hi,

I’m a new comer to Unity and would like to use this package in a C# class I’m working on, but I’m not sure of the syntax to use it the right way…
I would like to execute a given function (with different parameters) on 2 or 3 threads simutaneoulsy and then wait for each threads to finish it’s work to continue the main code execution.
This function will modify data at different points in an array, so I’d like to use threads to process the array faster.

How should I write this properly in C# ?

Not sure if I did understand you correctly, so correct me if I am wrong:

int[] myArray = new int[300];
..
void Foo(int a, int b)
{
  .. // do something with myArray[a] to myArray[b - 1]
}

void Start()
{
  var task1 = UnityThreadHelper.TaskDistributor.Dispatch(() => Foo(0, 100));
  var task2 = UnityThreadHelper.TaskDistributor.Dispatch(() => Foo(100, 200));
  var task3 = UnityThreadHelper.TaskDistributor.Dispatch(() => Foo(200, 300));

  // Wait for completion
  task1.Wait();
  task2.Wait();
  task3.Wait();
}

This will of course block the main thread execution until all 3 tasks have been completed.

If you dont want to block the main thread you can do something like this:

List<UnityThreading.Task> pendingTasks = new List<UnityThreading.Task>();
int[] myArray = new int[300];
..
void Foo(int a, int b)
{
  .. // do something with myArray[a] to myArray[b - 1]
}

void Start()
{
  for (int i = 0; i < 3; ++i)
    pendingTasks.Add(UnityThreadHelper.TaskDistributor.Dispatch(() => Foo(i * 100, i * 100 + 100)))
}

void Update()
{
  // needs System.Linq;
  if (pendingTasks.All(task => task.IsFinished))
    CalculationFinished();
}

void CalculationFinished()
{
  pendingTasks.Clear();
  ...
}

If you want to access the same element in different threads remember to lock the access to avoid race conditions, or separate the working data from each thread:

List<UnityThreading.Task<int[]>> pendingTasks = new List<UnityThreading.Task<int[]>>();
int[] myArray = new int[300];
..
int[] Foo(int[] isolatedArray)
{
  .. // do something with isolatedArraY
  return isolatedArray; // or the process result
}

void Start()
{
  // needs System.Linq;
  for (int i = 0; i < 3; ++i)
    pendingTasks.Add(UnityThreadHelper.TaskDistributor.Dispatch(() => Foo(myArray.Skip(i * 100).Take(100).ToArray()));
}

void Update()
{
  // needs System.Linq;
  if (pendingTasks.All(task => task.IsFinished))
    CalculationFinished();
}

void CalculationFinished()
{
  myArray = pendingTasks.SelectMany(task => task.Result).ToArray();
  pendingTasks.Clear();
  ...
}

Hope the code was correct, I wrote that without any reference or IDE near me :wink:

Hi,

thanks for the sample code. I’ve tried your first example, but it looks like it’s blocking the code execution forever.
I want to block the main thread execution only while the foo() function is working, and then restart it as soon as all are completed.
What is waiting the task.wait() function for, exactly ?

Also, should I create the task every game loop, or you I create them once, and reuse them all the time ?

[EDIT] ok forget it, I had an error in the foo() function wich was causing the freeze, but since it was in the thread, no error message was displayed
it’s now working properly :slight_smile:

Thank you !

Hey, great helper, but I’ve only got one problem:

Every time I use the Dispatcher, I get this error:

What should I do?

Thanks

Thanks.

Try to use UnityThreadHelper.Dispatcher.Dispatch(…)

I made a mistake while writing the little introduction code in the start post.

Thanks to share this code. It helps me a lot !!!

This look interesting but can someone please help give me an example of what are the applications or benefits of using Thread in Unity? How is it different from Invoke and InvokeRepeating?

Invoke and InvokeRepeating are based upon Coroutines, which basically means that the invoked operation is run in the mainthrread with no benefit of multithreading at all. Speak, the operation will block the mainthread until completion.

1 Like