Winforms调用异步方法挂断程序 [英] Winforms call to async method hangs up program

查看:50
本文介绍了Winforms调用异步方法挂断程序的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经解决了一段时间,但是现在我真的很想了解出了什么问题.我有一个相当简单的应用程序(这是一个用于跟踪的turtoise SVN插件,但是我可以使用一个普通的winforms应用程序重现该问题).

I have been working around this problem for a while, but now I would really like to understand what goes wrong. I have a rather simple application (it's a turtoise SVN plugin for youtrack, but I can reproduce the problem with a trivial winforms app).

我有一个异步方法ResolveIssue

public async Task<bool> ResolveIssue(Issue issue, int revision, string[] pathList)
{
    await Task.Delay(1000);

    return true;
}

创建死锁所需要做的就是在Button事件处理程序中调用此异步方法,并像这样

All I have to do to create a deadlock is call this async method in a Button event handler, and call Task.Wait or Task.Result, like this

private void buttonOk_Click(object sender, System.EventArgs e)
{
    var asyncResolvedIssue = api.ResolveIssue(issue, revision, pathList);
    if (asyncResolvedIssue.Result) {} // <== deadlock!
}

现在,我知道拥有一个异步方法并积极等待它是很奇怪的,但是为什么它会产生死锁?!

Now I understand it's rather weird to have an async method and actively wait for it, but why would it generate a deadlock?!

推荐答案

您的问题是因为您在调用.Result时阻塞了UI线程,并且告诉Task.Delay之后的继续在UI线程上运行.因此,您要阻止UI等待某个任务,而该任务在等待UI变为自由状态时被阻止,这是经典的死锁.

Your problem is because you are blocking the UI thread when you call .Result and you told the continuation after Task.Delay to run on the UI thread. So you are blocking the UI waiting for a task that is blocked on waiting for the UI to become free, a classic deadlock.

两种解决方案.首先,使按钮也单击异步.

Two solutions. First make the button click async too.

private async void buttonOk_Click(object sender, System.EventArgs e)
{
    var asyncResolvedIssue = api.ResolveIssue(issue, revision, pathList);
    if (await asyncResolvedIssue) {} // <== no deadlock!
}

事件处理程序是唯一允许您执行async void的地方.

Event handlers are the only place you are allowed to do async void.

另一个选项是告诉Task.Delay通过设置

The other option is tell Task.Delay it does not need to have the rest of its function run on the UI thread by setting ConfigureAwait(bool) to false.

public async Task<bool> ResolveIssue(Issue issue, int revision, string[] pathList)
{
    await Task.Delay(1000).ConfigureAwait(false);

    return true;
}

Task.Delay之后的代码行现在将在线程池线程而不是UI线程上运行,并且不会由于UI线程当前被阻塞的事实而被阻塞.

Now the line of code after the Task.Delay will run on a threadpool thread instead of the UI thread and will not be blocked by the fact that the UI thread is currently blocked.

这篇关于Winforms调用异步方法挂断程序的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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