Hello. Can someone help me with sync and async method? I tried to run long sync metod, it does not matter what, let’s say, that it is function named Test, it is sync and it takes 20-30 seconds. How to run in in another thread/task and not freeze unity? I tried Test(); and it complete properly, but freezes whole unity for 20-30 seconds, I also tried Task.Run(() => Test()); and it not freezes unity, but function Test not worked properly and also IEnumerator Test(); and StartCoroutine(Test()); but it works similar to first try, because I cant use yield return anywhere. So how to run this function in unity?
To run a simple thread you can use the Thread class in System.Threading.
Note that you cannot use any unity specific objects in your code which includes game objects, monobehaviours and any functions relating to these(such as physics). You would have to use the Job System as noted in the previous answer.
To make sure you dont run into problems there a few common multithreading issues that arise. The most common, by far, is called the race scenario.
Say you have a queue of objects and you want check to see if there is one in it then dequeue it and perform some action. You want this done in multiple threads so you use the same function in two different threads.
The problem arises when both objects checks the queue and sees one object in it, then they both try to dequeue the object. Only one will be able to get an object but the other one will throw an exception.
To remedy this you can use lock (just search lock c# in google to see how to use it)
So to use thread it is very simple just use it like this
Thread thread = new Thread(new ThreadStart(VoidParameterlessMethod));
thread.Start();
You can find more information here https://docs.microsoft.com/en-us/dotnet/api/system.threading.thread?view=netframework-4.8
Check out the Job system - This page has some examples and explanations of how to use it. If you are new to multithreading though be careful, its not a magic wand that you can wave to make things faster. You need to make sure that your code is thread safe (although I think unity does some of this for you) and that your code is properly implemented to work on a different thread.
You can execute a delegate on a pooled thread by using BeginInvoke(). You can use coroutines to synchronize the result with the main thread.
// expensive method
float LongCalculation(float input)
{
float expensiveResult;
// expensive calculation here
return expensiveResult;
}
IEnumerator MyCoroutine(float input)
{
System.Func<float, float> dlgt = LongCalculation;
var asyncResult = dlgt.BeginInvoke(input, null, null);
// the method now runs on a thread taken from the default pool; wait for the result
while(!asyncResult .IsCompleted)
yield return null; // result not ready, allow the unity main thread to continue
var expensiveResult = dlgt.EndInvoke(asyncResult); // retrieve the result
Debug.Log($"Result is {expensiveResult}");
}
it does not matter what
Well it does matter because many things in Unity are not thread safe and can not be used on a different thread. Using a coroutine does work however you have to include a yield statement somewhere in your code. Otherwise there’s no way.
Without knowing what is inside the method there’s no way to answer your question. You said you tried threading and using a coroutine and just said
but function Test not worked properly
We have no idea what that means. Maybe you violated basic threading rules and did not take care of potential concurrent access of data?
Again without knowing what you do inside the method there’s no resonable way your issue can be solved. Your issue could be summed up with: I have an issue I don’t want to tell you but I want a solution. You did not say what your method does and you did not properly explain what didn’t worked when you used threading.