Async-await无法正确恢复上下文 [英] Async-await does not recover context correctly

查看:89
本文介绍了Async-await无法正确恢复上下文的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个简单的winforms应用程序,它有一个初始化部分,对UI没有任何了解。此初始化运行异步。以下结构显示初始化部分:
$

I've a simple winforms application that has an initialization part that doen't know anything about UI. This initialization runs async. The following contruct shows that initialization part:

[STAThread]
private static void Main()
{
    var main = new Form1();

    using (var mre = new ManualResetEventSlim())
    {
        Initialization().ContinueWith(_ => mre.Set());

        while (!mre.Wait(TimeSpan.FromMilliseconds(25)))
        {
            Application.DoEvents();
        }
    }

    Application.Run(main);
}

private static async Task Initialization()
{
    await Task.Delay(100);
}

我们必须等到初始化才能显示主窗口。我不知道在主要等待异步操作的更好方法 - 欢迎提示。



之后我创建了一个包含以下代码的表单: br $>

We have to wait until initialization before the main window is shown. I don't know a better way to wait for an async operation in main - hints are welcome.

After that I created a form that contains the following code:

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
    }

    private async void Form1_Load(object sender, EventArgs e)
    {
        // Thread.CurrentThread.ManagedThreadId == 1;

        await Task.Delay(500);

        // Thread.CurrentThread.ManagedThreadId != 1 !!!!!!!
    }
}



这就是全部。该表单上没有控件。



问题是Form1_Load开始使用主线程的线程1(如预期的那样)。等待该延迟后,上下文无法正确恢复。等待Task.Delay(100)后运行代码的线程;不是主线。这会导致问题
通过访问该表单中包含的控件。



指定ConfigureAwait(true)将无法解决问题。



如何避免这种情况并强制等待按预期恢复主线程的上下文?



如果我们不出现问题更改以下内容之一:



不要等待使用此hacky构造的异步操作。但是我们需要等待初始化。

在等待构造之后创建Form1的实例。

问题是在Application.Run之前调用Application.DoEvents() (...)。



程序中强制解决该问题的代码可以简化为:




That's all. There are no controls on that form.

The Problem is that Form1_Load starts using thread 1 (as expected) which is the main thread. After await for that delay the context is not restored correctly. The thread running code after await Task.Delay(100); is not the main thread. That causes problems by accessing controls contained on that form.

Specifying ConfigureAwait(true) will not solve the problem.

How can I avoid that and force await to restore the context as expected to the main thread?

The Problem does not appear if we change one of the following things:

Do not wait for an async operation using this hacky construct. But we need to wait for our initialization.
Create the instance of Form1 after that waiting construct.
The problem is a call of Application.DoEvents() before Application.Run(...).

The code in Program that forces that problem can be simplyfied to:

[STAThread]
private static void Main()
{
    var main = new Form1();
    Application.DoEvents();
    Application.Run(main);
}



初始化()上的简单Wait()将导致死锁。


A simple Wait() on Initialization() will result in a deadlock.





推荐答案

如果
初始化不需要表格,然后尝试这个顺序:

If Initialization does not need the form, then try this order:

  
初始化()。等待();

   Initialization().Wait();

  
var
main =
new Form1();

  
Application.Run(main);

   Application.Run( main );

 

否则请考虑以下代码:

  
var
main =
new Form1();

  
Task.Run(初始化).Wait();

   Task.Run( Initialization ).Wait();

  
Application.Run(main);

   Application.Run( main );

 


这篇关于Async-await无法正确恢复上下文的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆