c#主线程等待对话框返回

时间:2016-08-22 11:02:32

标签: c# multithreading async-await uwp deadlock

我有以下方法:

public override bool SyncNavigationMethod()
{
    AsyncShowDialog().Wait();
    return true;
}

public Task AsyncShowDialog()
{
    //code to show dialog and process user input from the dialog.
}

当调用SyncNavigationMethod时,应用程序会陷入死锁状态。

我的猜测是它在等待AsyncShowDialog完成的MainThread上运行,并且显示的对话框无法调用它的回调,因为它是调用它的MainThread。因此,主线程等待自己,这是一个僵局。

更多信息:

  • 运行时 - UWP。
  • 设备:手机(如上所述)桌面(应用程序在显示对话框之前冻结)。
  • 我尝试在AsyncShowDialog上使用.Wait()\ .Result。
  • 在调用AsyncShowDialog以阻止代码在AsyncShowDialog运行时继续进行时,我尝试使用ManualResetEvent。

我是否正确怀疑死锁?

如何在没有此死锁的情况下从SyncNavigationMethod调用AsyncShowDialog?

感谢。

1 个答案:

答案 0 :(得分:2)

我将从 Stephen Cleary 的最佳博客post开始,它解释了异步调用的同步阻塞如何导致死锁,这是真的除Console之外的所有系统,它没有UI上下文线程:

现在关于你的代码和要点:

  

所以,主线程等待自己,这是一个僵局。

是的,你已经正确地理解它是一个死锁,因为Mainthread阻塞了自己

Wait, Result and ManualResetEvent,它们都同步阻止异步代码,因此结果相同

可能的解决方案:

如果通话是Rest APIweb based call,那么请将所有内容Async和IIS确保它可以返回后级Async-Await执行,类似于:

public async override Task<bool> SyncNavigationMethod()
{
    await AsyncShowDialog();
    return true;
}

public async Task AsyncShowDialog()
{
    await SomeOperation();
}

Task<bool>的返回值将自动解包

其他选择:

如果您无法制作SyncNavigationMethod() Async,请尝试以下操作:

public override bool SyncNavigationMethod()
    {
        List<Task> taskList = new List<Task>();
        taskList.Add(AsyncShowDialog());
        Task.WhenAll(taskList.ToArray());
        return true;
    }

    public async Task AsyncShowDialog()
    {
        await SomeOperation();
    }