C#非async方法如何确保LatestDate变量更新后再执行后续代码
问题核心原因
- 你在同步方法中使用了
await语法,但方法本身未标记async,本身就存在编译错误 - 调用
Wait()阻塞主线程会触发死锁:Firebase异步任务完成后需要切回Unity主线程执行回调,但主线程已经被Wait()阻塞等待任务结束,导致回调永远无法执行,latestDate永远停留在初始值0,严重时直接触发程序崩溃
解决方案1:使用async/await(推荐)
Unity 2018+ 都支持原生async/await语法,直接修改方法返回值为Task<bool>即可安全等待异步执行,不会阻塞主线程:
// 方法标记async,返回值改为Task<bool> public async Task<bool> CheckWatchConnection() { var latestDate = 0; var now = DateTimeOffset.Now.ToUnixTimeMilliseconds(); bool connected = false; DatabaseReference lastHistoryEntry = DBreference.Child("users").Child(User.UserId).Child("History"); var query = lastHistoryEntry.OrderByKey().LimitToLast(1); // 直接await异步任务,主线程不会阻塞 var snapshot = await query.GetValueAsync(); if (snapshot.Exists) { latestDate = int.Parse(snapshot.Child("Date").Value.ToString()); long diff = now - latestDate; connected = diff < 10; } return connected; }
调用方法时也使用await接收结果:
// 调用处示例,Unity生命周期方法也可标记async void private async void Start() { bool isConnected = await CheckWatchConnection(); // 拿到结果后执行后续逻辑 Debug.Log($"连接状态:{isConnected}"); }
解决方案2:回调模式(适配无法修改方法签名的场景)
如果不能修改原方法的返回类型,就放弃同步返回值,改用回调委托接收结果:
// 增加回调参数,异步任务完成后触发回调 public void CheckWatchConnection(Action<bool> onComplete) { var now = DateTimeOffset.Now.ToUnixTimeMilliseconds(); DatabaseReference lastHistoryEntry = DBreference.Child("users").Child(User.UserId).Child("History"); var query = lastHistoryEntry.OrderByKey().LimitToLast(1); query.GetValueAsync().ContinueWith(task => { if (task.IsFaulted || !task.Result.Exists) { // 错误或无数据时回调返回false onComplete?.Invoke(false); return; } int latestDate = int.Parse(task.Result.Child("Date").Value.ToString()); long diff = now - latestDate; bool connected = diff < 10; // 如果回调中需要操作Unity UI/组件,需要把回调抛到主线程执行 // 可直接用UnityMainThreadDispatcher工具类,或自己实现主线程任务队列 UnityMainThreadDispatcher.Instance.Enqueue(() => onComplete?.Invoke(connected)); }); }
调用方式:
CheckWatchConnection(isConnected => { // 此处拿到结果执行后续逻辑 Debug.Log($"连接状态:{isConnected}"); });
内容的提问来源于stack exchange,提问作者Thekra
相关产品推荐
相关产品推荐

