【发布时间】:2015-01-19 08:09:25
【问题描述】:
假设我有一个尝试处理多线程环境的Form;因此,它会在完成任何 UI 修改之前检查它是否在 UI 线程上运行:
partial class SomeForm : Form
{
public void DoSomethingToUserInterface()
{
if (InvokeRequired)
{
BeginInvoke(delegate { DoSomethingToUserInterface() });
}
else
{
… // do the actual work (e.g. manipulate the form or its elements)
}
}
}
现在假设我在该方法的… 部分执行了一些冗长的操作;因此,我想使用 async/await 使其异步。
鉴于我应该更改方法签名以返回Task 而不是void(以便可以捕获异常),我将如何实现执行BeginInvoke 的部分?它应该返回什么?
public async Task DoSomethingToUserInterfaceAsync()
{
if (InvokeRequired)
{
// what do I put here?
}
{
… // like before (but can now use `await` expressions)
}
}
【问题讨论】:
-
顺便说一句,我正在考虑提取冗长的操作,一旦完成,将其结果作为参数传递给
DoSomethingToUserInterface,它不再需要是async(从而避免了这个问题此处介绍)。不过,我仍然对解决方案感兴趣。 -
一般来说,
async/await应该不需要Invoke()。 IE。您曾经遇到过从潜在的非 GUI 线程上下文调用这些方法的情况,现在您应该能够配置您的代码来完全避免这种情况。因此,与其问如何在这里更改方法签名,不如问如何更改调用者以避免首先需要调用。 -
@PeterDuniho:这似乎是一个合理的建议。所以我基本上必须追溯导致
DoSomethingToUserInterfaceAsync的调用者链(直到某些可能是 Windows 窗体 UI 事件处理程序的方法),让所有这些调用者方法也使用async/await? -
@stakx 为什么会问这个问题?
await保证异步操作后的代码会在原线程上运行。如果该线程是 UI 线程,则代码将在 UI 线程上运行,您根本不需要 BeginInvoke。您的async方法的调用者是否使用Task.Run? -
@PanagiotisKanavos:我问是因为我现在才学习所有这些,还不知道对于像你这样更有经验的人来说什么是显而易见的。 - 你的评论很有帮助。我想我现在明白了what Peter Duino suggested above。谢谢!
标签: c# winforms async-await c#-5.0 invokerequired