Search code examples
firebaseunity-game-enginefirebase-realtime-databasetimeouttask

How to timeout Firebase Task in Unity


This issue is driving me nuts :) Assuming that I have a simple async Task:

async Task AddPoints()
{


    await usersDbReference.Child(currentUser).Child("Score").SetValueAsync(newScore).ContinueWith(task =>
    {
        if(task.IsFaulted || task.IsCanceled)
        {
            Debug.Log("Couldn't complete task");
        }
    });

}

What is the simplest way to add the timeout, for example 10 seconds, after which I will show pop up to the user to check his/her internet connection?

Thank you in advance!

EDIT: I tried below code but it makes the unity crash:

int timeout = 1000;
var task = SomeOperationAsync();
if (await Task.WhenAny(task, Task.Delay(timeout)) == task) {
    // task completed within timeout
} else { 
    // timeout logic
}

I'm using Unity (api compatibility level .Net Standard 2.0, I assume that crash is because of this?)

What I want to achieve: In case the user doesn't have the internet connection I want to either timeout the task and cancel it or just cancel it after finding out there is no internet connection.

EDIT:

I modified the code. So I have a simple task with cancel token:

async Task CheckTask(CancellationToken csToken)
{

    string firstChild = "user";
    string secondChild = "testuser";

    await FirebaseDatabase.DefaultInstance.RootReference.Child(firstChild).Child(secondChild).GetValueAsync().ContinueWith(task =>
    {
        if(task.IsFaulted || task.IsCanceled)
        {
            Debug.Log("Task was canceled");
        }
    });
}

Then I'm calling it from async void:

public async void FirebaseLogin()
{
    bool taskDidntComplete = false;

    Debug.Log("Started task");

    CancellationTokenSource cs = new CancellationTokenSource();

    try
    {
        var loginTask = CheckTask(cs.Token);

        if(loginTask.IsCanceled)
        {
            Debug.Log("Canceled");
        }

        if (await Task.WhenAny(loginTask, Task.Delay(10000)) == loginTask) 
        {
            taskDidntComplete = false;
        } 
        else 
        { 
            taskDidntComplete = true;
            Debug.Log(taskDidntComplete);
            cs.Cancel();
            throw new TimeoutException();
        }
    }
    catch (Exception e)
    {
        Debug.Log(e);
    }
    finally
    {
    }
}

And while everything works fine and it shows the exception, it doesn't cancel the task. Would be very grateful if someone could tell me what I'm doing wrong.

EDIT2: Works perfect in Unity, doesnt work on Android... Anyone can help? I'm desperate now haha

public async void FirebaseLogin()
{

    Debug.Log("Started task");

    CancellationTokenSource cs = new CancellationTokenSource();

    try
    {
        var loginTask = CheckTask(cs.Token);

        if(loginTask.IsCanceled)
        {
            Debug.Log("Canceled");
            netTestCheck.text = "Canceled";
        }

        if (await Task.WhenAny(loginTask, Task.Delay(10000)) == loginTask) 
        {
            //netTestCheck.text = "Completed";
        } 
        else 
        { 
            netTestCheck.text = "Failed";
            cs.Cancel(false);
            //throw new TimeoutException();
        }

        cs.Token.ThrowIfCancellationRequested();
    }
    catch (Exception e)
    {
        netTestCheck.text = "Failed2";
        Debug.Log(e);
    }
    finally
    {

    }

Solution

  • It unfortunately won't work on Android because app will keep on calling to Firebase. Fortunately found the way around :D