WinForm中为何async Task内RichTextBox.AppendText无需Invoke?
原因说明
你在uplineCount异步方法里直接调用AppendText不需要手动用Invoke切UI线程,核心是WinForm下async/await的同步上下文自动捕获机制帮你做了线程调度,所有操作控件的代码实际都跑在UI线程上,具体逻辑:
- 你的
btnCount_Click是UI线程触发的按钮点击事件,在这个事件里调用uplineCount()时,方法初始运行环境就是UI线程,第一次循环执行rtCount.AppendText的时候本来就在合法的UI线程里,不存在跨线程访问的问题。 - 当执行到
await Task.Delay(1000)时,await会自动捕获当前线程绑定的UI同步上下文(WinForm里是WindowsFormsSynchronizationContext)。等1秒延时结束后,await后面的代码会被自动调度回之前捕获的UI线程执行,所以后续每一轮循环调用AppendText的时候,始终都在UI线程上,当然不需要手动调用Invoke。
额外说明
你写的ContinueWith块里必须用Invoke,是因为ContinueWith默认不会捕获当前的同步上下文,它的延续任务默认会扔到线程池的工作线程上跑,工作线程没有直接访问UI控件的权限,所以必须手动通过Invoke把操作封送回UI线程。
另外提一句,你代码里的Task.WhenAll(task);是无效代码,因为没有加await,这行执行的时候不会等待计数任务完成,会直接往下走。
内容的提问来源于stack exchange,提问作者Yune
相关产品推荐
相关产品推荐

