如果从未返回等待任务,异步方法是否同步?

时间:2019-02-28 08:01:37

标签: c# wpf async-await thread-safety deadlock

我有一个在WPF应用程序中的UI线程上调用的构造函数。在它内部,它调用async方法,但是必须以同步方式完成。所以我试图打电话给wait,但是造成了僵局,我明白原因。因此,我介绍了表明方法应以异步还是同步方式运行的参数。像这样:

// constructor that is called on UI thread
public MyClass()
{
    Method1(false).Wait();
}

public async Task Method1(bool runAsync)
{
    await Method2(runAsync);
}

public async Task Method2(bool runAsync)
{
    if (runAsync)
    {
        await Task.Run(() => Thread.Sleep(1000));
    }
    else
    {
        Thread.Sleep(1000);
    }
}

我不想使用ConfigureAwait,因为我希望所有内容都可以在UI线程上运行。将Method1(false).Wait();会导致死锁(使用安全吗)?我测试了很多,但没有测试,但是我不确定。最后,我真正的问题是:如果从未执行过“ await Task.Run(...”),那么我的方法是否完全同步呢?我找到了与此主题相关的几篇文章,但没有一篇直接回答我的问题。

2 个答案:

答案 0 :(得分:0)

  

我有一个在WPF应用程序中的UI线程上调用的构造函数。在它内部,它调用async方法,但必须以同步方式完成。

我要在那里阻止你。最好的解决方案是 not 在UI线程上运行同步/阻止代码。这会降低您的用户体验。相反,您应该重组代码,这样一来您就永远不会处于这种情况。

显示UI时,UI框架会要求您的代码显示数据。您的代码应同步运行并立即返回(不阻塞)。但是您的代码还需要执行一些异步工作才能显示数据。因此那里存在冲突。

解决方案是为UI设计一种中间状态,例如“正在加载...”消息或微调框。然后,当您的代码启动时,它可以同步/立即显示“正在加载”状态(并 start 异步操作),而当异步数据到达时,代码 updates UI进入“最终”状态。

我在async MVVM data上的文章中更详细地讨论了这种模式。

答案 1 :(得分:0)

与其在构造时费力地解决异步问题(您的阻塞解决方案不太好),何不编写一个异步工厂来喷出这些对象?

class MyClass
{
    public MyClass()
    {

    }

    public async Task Method2(bool runAsync)
    {
        //async immediately
        await Task.Delay(1000); //no Thread.Sleep. Blocking code != good
    }
}

然后

public MyClassFactory
{
    public async Task<MyClass> GetAsync()
    {
        var c = new MyClass();
        await c.Method2();
        return c;
    }
}