繁体   English   中英

为什么'await'会改变WinForms program.cs中的线程上下文

[英]Why does 'await' change the thread context in WinForms program.cs

使用await调用异步方法的正常行为是它的上下文保持不变,如下例所示:

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

    private async void Form1_Load(object sender, EventArgs e)
    {
        //main thread here
        await SampleAsync();
        //stays as main thread
        var g = 10;
    }

    static async Task SampleAsync()
    {
        await Task.Delay(1000);
    }
}

但是当我在Winforms主控制台方法调用中使用它时,这种行为不再成立:在调用await方法之后,线程从主线程更改为工作线程。 为什么是这样? 我希望它在等待调用后保持在Main(UI线程)上。

    [STAThread]
    static void Main()
    {
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);
        MainAsync().Wait();
    }

    static async Task MainAsync()
    {
        Application.Run(new Form1());
        //Main Thread here
        await Task.Delay(1000);
        //Why does it turn in to worker thread here? ConfigureAwait(false) is not used here?!
        var g = 5;
        //Run other Application.Run() if certain conditions apply; but I need to be in the Main Thread.
    }

如果你想知道我想要实现什么,我试图捕获异步方法中的错误,MainAsync,而不是Main,以便我可以避免从AggregateException( https://msdn.microsoft)解开错误。 com / en-us / magazine / JJ991977.aspx ;图4)。 我还想留在UI线程中,这样我就可以在UI线程中运行其他Application.Run。

因为Application.Run是“运行”主线程上的延续,所以一旦Application.Run返回SynchronizationContext.Current ,则为“UI线程”取消设置,因此await必须使用默认上下文,即ThreadPool。

因为此时没有UI,我建议在此时进行同步等待( .Wait() )而不是await ,这将确保您仍然在以后的Application.Run调用的同一个STA线程上。

编辑 :没有看到你提到关于解开AggregateException,所有等待是用AggregateException做的相当于

catch(AggregateException ex)
{
    ExceptionDispatchInfo.Capture(ex.InnerException).Throw();
}

这导致重新引发AggregateException的第一个异常,而不会弄乱它的堆栈跟踪。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM