异步操作 hangs/deadlocks,为什么? (不是等待结果,也不是 ConfiguringAwait)
Async action hangs/deadlocks, why? (not waiting for Result, nor ConfiguringAwait)
首先,对于另一个 "why my async action hangs" 问题感到抱歉,但我相信这个问题非常不同。
调查了几十个类似的问题,异步操作死锁的问题是将自己锁在外面(.Result
),使用有限的资源或不正确地使用库组件(网络请求似乎很流行)。在下面的示例中,我无法从上面找到 any:
private async Task ExecuteAsync(Task<int> task)
{
// entering on current thread, that is the main UI thread
await task // execute "task" asynchronnously (on a different thread)
.ConfigureAwait(false); // when done, no need to return to main thread
MessageBox.Show("success"); // succes indicator
}
public MainWindow() //wpf window ctor
{
InitializeComponent();
this.Loaded += MainWindow_Loaded;
}
private void MainWindow_Loaded(object sender, RoutedEventArgs e)
{
var task = new Task<int>(() => 42); // make an Action wrapping sychronnous method
// fire and forget, never caring for .Result, disard even the task
var _ = ExecuteAsync(task).ConfigureAwait(false);
}
我已尽最大努力对示例进行评论,以解释事物(应该)如何工作,但我的解释中一定有错误。即使 MainWindow
ctor 没有死锁,操作 () => 42
也不会执行,并且不会显示 "success" 消息。经过一些调试后,我设法修复了示例(使用 Task.FromResult
),但我仍然不确定它现在有什么问题,更重要的是为什么。
我的推理有什么错误,为什么从来没有采取行动 executed/finished?
您没有开始任务!你只是声明了它。只是 await
ing 它不会 "fire" 它。
private async Task ExecuteAsync(Task<int> task)
{
// at first do start the task
task.Start();
await task.ConfigureAwait(false);
MessageBox.Show("success");
}
请注意,ConfigureAwait(false)
不保证将在不同的线程上继续执行。它只是说您 不需要 在原始线程上恢复它。不建议在非 UI 线程上恢复 UI 工作(如 MessageBox.Show()
)。
正如 指出的那样,如果你想包装一个同步方法并让它 运行 在不同的线程上,你应该使用 Task.Run()
:
var task = Task.Run(() => YourSynchronousCall());
首先,对于另一个 "why my async action hangs" 问题感到抱歉,但我相信这个问题非常不同。
调查了几十个类似的问题,异步操作死锁的问题是将自己锁在外面(.Result
),使用有限的资源或不正确地使用库组件(网络请求似乎很流行)。在下面的示例中,我无法从上面找到 any:
private async Task ExecuteAsync(Task<int> task)
{
// entering on current thread, that is the main UI thread
await task // execute "task" asynchronnously (on a different thread)
.ConfigureAwait(false); // when done, no need to return to main thread
MessageBox.Show("success"); // succes indicator
}
public MainWindow() //wpf window ctor
{
InitializeComponent();
this.Loaded += MainWindow_Loaded;
}
private void MainWindow_Loaded(object sender, RoutedEventArgs e)
{
var task = new Task<int>(() => 42); // make an Action wrapping sychronnous method
// fire and forget, never caring for .Result, disard even the task
var _ = ExecuteAsync(task).ConfigureAwait(false);
}
我已尽最大努力对示例进行评论,以解释事物(应该)如何工作,但我的解释中一定有错误。即使 MainWindow
ctor 没有死锁,操作 () => 42
也不会执行,并且不会显示 "success" 消息。经过一些调试后,我设法修复了示例(使用 Task.FromResult
),但我仍然不确定它现在有什么问题,更重要的是为什么。
我的推理有什么错误,为什么从来没有采取行动 executed/finished?
您没有开始任务!你只是声明了它。只是 await
ing 它不会 "fire" 它。
private async Task ExecuteAsync(Task<int> task)
{
// at first do start the task
task.Start();
await task.ConfigureAwait(false);
MessageBox.Show("success");
}
请注意,ConfigureAwait(false)
不保证将在不同的线程上继续执行。它只是说您 不需要 在原始线程上恢复它。不建议在非 UI 线程上恢复 UI 工作(如 MessageBox.Show()
)。
正如 Task.Run()
:
var task = Task.Run(() => YourSynchronousCall());