System.Windows.Forms.Timer异步回调中await重复执行的原因及解决方法
System.Windows.Forms.Timer异步回调重复执行的问题分析与解决
问题原因
System.Windows.Forms.Timer的Tick事件确实在UI线程触发,但Async Sub的特性导致了回调重叠:
当Tick方法执行到Await SaveAsync()时,方法会挂起并立即返回给调用方(Timer的触发机制),此时UI线程被释放,Timer会判定上一次回调已完成,到了下一个触发周期就会再次触发Tick事件,最终导致前后两次回调的异步操作重叠执行。
解决方法
方案1:手动控制Timer启停
在Tick事件开头禁用Timer,确保所有异步操作完成后再重新启用,同时通过Try/Finally保证异常情况下Timer状态也能恢复:
Private Async Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick Timer1.Enabled = False Try For i=1 To 6 If(some condition is true in array index) Await SaveAsync() 'set to false the condition in array index after save End If Next Finally Timer1.Enabled = True End Try End Sub
方案2:使用处理标志位
添加布尔变量标记当前是否正在处理回调,进入Tick事件时先检查标记,避免重复执行:
Private isProcessing As Boolean = False Private Async Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick If isProcessing Then Return isProcessing = True Try For i=1 To 6 If(some condition is true in array index) Await SaveAsync() 'set to false the condition in array index after save End If Next Finally isProcessing = False End Try End Sub
额外说明
如果数据库操作不依赖UI线程,也可以考虑改用System.Timers.Timer(默认在ThreadPool线程触发),但要注意跨线程操作UI时需通过Invoke切换回UI线程。
内容的提问来源于stack exchange,提问作者Alfons Deda
相关产品推荐
相关产品推荐

