异步操作挂起/死锁,为什么? (不等待结果,也不等待ConfigureAwait)

问题描述 投票:0回答:1

[首先,对于另一个“为什么我的异步操作挂起”问题,我们感到抱歉,但是我相信这个问题已经足够不同了。调查数十个类似的问题,异步操作死锁的问题要么是锁定自己(.Result),要么使用有限的资源,要么不正确地使用库组件(Web请求似乎很流行)。在以下示例中,我找不到从上方任何一个

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, dont return to main thread use a new one
    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,并且不会显示“成功”消息。经过一些调试后,我设法修复了该示例(使用Task.FromResult),但我仍不确定当前存在什么问题,甚至更重要的是为什么。我的推理有什么错误,为什么该动作从未执行/完成?

c# async-await deadlock
1个回答
3
投票

您没有开始任务!您只声明了它。只需将其await设置为“发射”即可。

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())。

© www.soinside.com 2019 - 2024. All rights reserved.