如何在 Unity 中使 Firebase 任务超时

How to timeout Firebase Task in Unity

这个问题快把我逼疯了:) 假设我有一个简单的异步任务:

async Task AddPoints()
{


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

}

添加超时的最简单方法是什么,例如 10 秒,之后我将向用户显示弹出窗口以检查 his/her 互联网连接?

提前致谢!

编辑: 我尝试了下面的代码,但它使统一崩溃:

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

我正在使用 Unity(api 兼容级别 .Net Standard 2.0,我认为崩溃是因为这个?)

我想达到的目标: 如果用户没有互联网连接,我想使任务超时并取消它,或者在发现没有互联网连接后直接取消它。

编辑:

我修改了代码。所以我有一个简单的取消令牌任务:

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");
        }
    });
}

然后我从 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
    {
    }
}

虽然一切正常并且显示异常,但它并没有取消任务。如果有人能告诉我我做错了什么,将不胜感激。

EDIT2:在 Unity 中运行完美,在 Android 上运行不正常...有人可以提供帮助吗?我现在很绝望哈哈

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
    {

    }

如果您能分享崩溃的异常或堆栈跟踪,将会有所帮助(如果您已经在 Firebase 生态系统中,integrating Crashlytics 可能会有所帮助)。

虽然我无法在你的示例代码中发现任何看起来特别糟糕的东西,但如果实际的 Task 由于任何原因失败(比如你打开飞行模式进行测试,并且之前引发了一个合适的异常你的超时)会在那里引发你没有处理的异常。

我建议在您的街区周围放置一个 try/catch,例如:

try {
    int timeout = 1000;
    var task = SomeOperationAsync();
    if (await Task.WhenAny(task, Task.Delay(timeout)) == task) {
        // task completed within timeout
    } else { 
        // timeout logic
    }
} catch (Exception e) {
    Debug.LogError($"{e} occurred!");
}

它可能是 DatabaseException,但我会先检查一下,然后你才能得到比 Exception 更具体的信息。

如果有帮助请告诉我!

--帕特里克

不幸的是,它无法在 Android 上运行,因为应用程序将继续调用 Firebase。幸运的是找到了方法 :D