简体   繁体   中英

How do I properly block code execution until callback

I am new to Unity and C# and trying to query my Firebase Realtime Database, but the code does not block for the callback to finish.

I have tried implementing callbacks but this does not seem to work.

static public void ReadFromDb(int level, Action<int> callback) 
{
    int return_value = -1;
    string sessionId = PlayerPrefs.GetString("SessionID");

    FirebaseDatabase.DefaultInstance.GetReference("users/"+sessionId).GetValueAsync().ContinueWith(task => {
        if (task.IsFaulted) 
        {
            // Handle the error...
            Debug.Log("Task faulted");
            callback(return_value);
        } 
        else if (task.IsCompleted) 
        {
            DataSnapshot snapshot = task.Result;
            string score_string = (snapshot.Child(level.ToString()).Value).ToString();
            Debug.Log("score_string " + score_string);
            return_value = int.Parse(score_string);
            callback(return_value);
        }
    });
}


public void LevelComplete() 
{
    DatabaseCode.writeDatabase(SceneManager.GetActiveScene().buildIndex + 1, counter);
    DatabaseCode.ReadFromDb(SceneManager.GetActiveScene().buildIndex + 1, (result) => {
        prevlevelscore = result;
        Debug.Log("result " + result.ToString());
    });
    prevscore = prevlevelscore;
    Debug.Log("Returned value: " + prevlevelscore.ToString());
    SceneManager.LoadScene(SceneManager.GetActiveScene().buildIndex + 1);
}

In LevelComplete() , Debug.Log("Returned value: " + prevlevelscore.ToString()); executes before prevlevelscore = result;
I want to make sure that the value of prevlevelscore is updated before executing Debug.Log .

Put the rest of the code inside the callback too:

public void LevelComplete() 
{
    DatabaseCode.writeDatabase(SceneManager.GetActiveScene().buildIndex + 1, counter);
    DatabaseCode.ReadFromDb(SceneManager.GetActiveScene().buildIndex + 1, (result) => {
        Debug.Log("result " + result.ToString());
        prevscore = result;
        SceneManager.LoadScene(SceneManager.GetActiveScene().buildIndex + 1);
    });    
}

Your problem is that your ReadFromDb method returns before being finished. You can solve this issue by putting all your code in the callback (but you won't be able to do that all the time) or you can use the async await pattern.

Make ReadFromDb async:

    static public async Task ReadFromDb(int level, Action<int> callback) 
    {
        int return_value = -1;
        string sessionId = PlayerPrefs.GetString("SessionID");

        await FirebaseDatabase.DefaultInstance.GetReference("users/"+sessionId).GetValueAsync().ContinueWith(task => {
            if (task.IsFaulted) 
            {
                // Handle the error...
                Debug.Log("Task faulted");
                callback(return_value);
            } 
            else if (task.IsCompleted) 
            {
                DataSnapshot snapshot = task.Result;
                string score_string = (snapshot.Child(level.ToString()).Value).ToString();
                Debug.Log("score_string " + score_string);
                return_value = int.Parse(score_string);
                callback(return_value);
            }
        });
    }

Note the await keywork before your GetValueAsync().ContinueWith because this precise code is asynchronous and needs to be awaited if you want to hold code execution until the result has been fetched.

And in your caller:

    public async Task LevelComplete() 
    {
        DatabaseCode.writeDatabase(SceneManager.GetActiveScene().buildIndex + 1, counter);
        await DatabaseCode.ReadFromDb(SceneManager.GetActiveScene().buildIndex + 1, (result) => {
            prevlevelscore = result;
            Debug.Log("result " + result.ToString());
        });
        prevscore = prevlevelscore;
        Debug.Log("Returned value: " + prevlevelscore.ToString());
        SceneManager.LoadScene(SceneManager.GetActiveScene().buildIndex + 1);
    }

This method becomes async as well (because asynchronicity propagates). Again, the await keyword will hold on execution until the readFromDb method has finished. Which means that your data will be ready.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM