HiveBrain v1.2.0
Get Started
← Back to all entries
patterncsharpMinor

Wait for multiple functions to run

Submitted by: @import:stackexchange-codereview··
0
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).

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 Interlocked class, you will still need additional synchronization to make sure, that Callback is not called while Start is running.



  • Term coroutine has 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.