如何在 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
这个问题快把我逼疯了:) 假设我有一个简单的异步任务:
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