我有一个在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(...”),那么我的方法是否完全同步呢?我找到了与此主题相关的几篇文章,但没有一篇直接回答我的问题。
答案 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;
}
}