如何在Xamarin Forms中实现异步版Device.StartTimer?
实现Xamarin Forms中Device.StartTimer的异步版本
你的核心问题在于Device.StartTimer的回调是同步返回bool的,无法直接等待异步操作完成,原代码里的retVal会在异步的RefreshAsync执行前就返回初始值false,导致定时器只执行一次就停止,且得不到正确结果。
解决方案:封装异步版本的定时器
我们可以自己实现异步定时器逻辑,用Task.Delay结合循环替代Device.StartTimer,这样就能在回调里安全等待异步方法的结果:
public static async Task AsyncStartTimer(TimeSpan interval, Func<Task<bool>> callback) { do { // 等待定时器间隔 await Task.Delay(interval); // 执行异步回调,获取是否继续的结果 var shouldContinue = await callback().ConfigureAwait(false); if (!shouldContinue) break; } while (true); }
替换原代码使用
把原来的Device.StartTimer调用换成这个异步方法,回调里直接处理异步逻辑:
// 启动异步定时器,无需担心同步返回的问题 _ = AsyncStartTimer(TimeSpan.FromMilliseconds(500), async () => { // 直接await你的异步方法,获取结果 var retVal = await this.RefreshAsync().ConfigureAwait(true); // 返回是否继续执行定时器 return retVal; });
针对你的业务场景说明
你的RefreshAsync会等待iOS的ShowAlertAsync(Toast动画完成),现在用这个异步定时器后,每次定时器触发都会等待Toast动画完成,再根据retVal决定是否继续下一次定时,完全匹配你的需求。
原代码的问题分析
Device.StartTimer的回调必须同步返回,你在里面用Device.BeginInvokeOnMainThread启动的异步委托会在稍后执行,所以retVal会立即返回初始的false,定时器直接停止。- 即使你尝试在回调里等待
TaskCompletionSource的任务,也会阻塞UI线程(StartTimer的回调在UI线程执行),导致界面卡死,这是必须避免的。
内容的提问来源于stack exchange,提问作者anon
相关产品推荐
相关产品推荐

