patterncsharpMinor
Wait for multiple functions to run
Viewed 0 times
waitformultiplefunctionsrun
Problem
In my loading scene I want to run multiple functions (IO from the disk) and start the app after they are completed.
This is in my loading class. (Note: This is unity 3d and the public variables to get access to other objects is based on Unity best practices).
I do something similar in both Logger and Parser (counting coroutines and decrementing when they finish before invoking the callback received). Is there a better way to do this when I need to expand the number of functions I'm calling?
This is in my loading class. (Note: This is unity 3d and the public variables to get access to other objects is based on Unity best practices).
public Logger MyLogger;
public Parser MyParser;
// ... more
private int coroutineCount = 0;
void Start()
{
MyLogger.LogLastMonth(Callback);
coroutineCount++;
MyParser.ParseFiles(Callback);
coroutineCount++;
}
public void Callback()
{
coroutineCount--;
if (coroutineCount <= 0)
{
SceneManager.LoadScene("GameScene");
}
}I do something similar in both Logger and Parser (counting coroutines and decrementing when they finish before invoking the callback received). Is there a better way to do this when I need to expand the number of functions I'm calling?
Solution
- Your code is not thread-safe on many levels. Even if you replace regular increments/decrements with methods from
Interlockedclass, you will still need additional synchronization to make sure, thatCallbackis not called whileStartis running.
- Term
coroutinehas a specific meaning in context of Unity, so you should probably use different word to avoid confusion.
-
I don't know what is the recommended way of doing these things in Unity. In absence of TPL (I assume Unity still uses .Net 3.5), the easiest solution I can think of, that does not require good understanding of threading, is to return WaitHandles from your async methods:
void Start()
{
var handles = new List();
handles.Add(MyLogger.LogLastMonth());
handles.Add(MyParser.ParseFiles());
//etc...
ThreadPool.QueueUserWorkItem(_ =>
{
WaitHandle.WaitAll(handles.ToArray());
//at this point you might want to dispose handles
//if you do not plan to re-use them
//Make sure this call is thread-safe.
//If it is not, you will have to dispatch this call back to main thread
// or set some bool field here, and move the call to Update.
SceneManager.LoadScene("GameScene");
});
}Code Snippets
void Start()
{
var handles = new List<WiatHandle>();
handles.Add(MyLogger.LogLastMonth());
handles.Add(MyParser.ParseFiles());
//etc...
ThreadPool.QueueUserWorkItem(_ =>
{
WaitHandle.WaitAll(handles.ToArray());
//at this point you might want to dispose handles
//if you do not plan to re-use them
//Make sure this call is thread-safe.
//If it is not, you will have to dispatch this call back to main thread
// or set some bool field here, and move the call to Update.
SceneManager.LoadScene("GameScene");
});
}Context
StackExchange Code Review Q#157026, answer score: 5
Revisions (0)
No revisions yet.