【发布时间】:2018-09-28 20:51:17
【问题描述】:
我们有一个使用异步初始化过程的 winforms 应用程序。简而言之,您可以说应用程序将运行以下步骤:
- 初始化 - 异步运行
- 显示主窗体
- Application.Run()
当前存在且工作的代码如下所示:
[STAThread]
private static void Main()
{
SynchronizationContext.SetSynchronizationContext(new WindowsFormsSynchronizationContext());
var task = StartUp();
HandleException(task);
Application.Run();
}
private static async Task StartUp()
{
await InitAsync();
var frm = new Form();
frm.Closed += (_, __) => Application.ExitThread();
frm.Show();
}
private static async Task InitAsync()
{
// the real content doesn't matter
await Task.Delay(1000);
}
private static async void HandleException(Task task)
{
try
{
await Task.Yield();
await task;
}
catch (Exception e)
{
Console.WriteLine(e);
Application.ExitThread();
}
}
Mark Sowul here 非常详细地描述了它的工作原理。
从 C# 7.1 开始,我们可以在 main 方法中使用异步任务。我们以直接的方式进行了尝试:
[STAThread]
private static async Task Main()
{
SynchronizationContext.SetSynchronizationContext(new WindowsFormsSynchronizationContext());
try
{
await StartUp();
Application.Run();
}
catch (Exception e)
{
Console.WriteLine(e);
Application.ExitThread();
}
}
private static async Task StartUp()
{
await InitAsync();
var frm = new Form();
frm.Closed += (_, __) => Application.ExitThread();
frm.Show();
}
private static async Task InitAsync()
{
// the real content doesn't matter
await Task.Delay(1000);
}
但这不起作用。原因很清楚。第一个await 之后的所有代码都将被转发到消息循环。但是消息循环还没有开始,因为启动它的代码 (Application.Run()) 位于第一个 await 之后。
删除同步上下文将解决问题,但会导致在不同线程中运行await 之后的代码。
将代码重新排序以在第一个 await 之前调用 Application.Run() 将不起作用,因为这是一个阻塞调用。
我们尝试使用具有async Task Main() 的新功能,它允许我们删除难以理解的HandleException-解决方案。但我们不知道怎么做。
你有什么建议吗?
【问题讨论】:
标签: winforms async-await main c#-7.1