8

我知道Task.Wait在 UI 线程中调用是不好的。它会导致死锁。请参阅

构造函数调用异步方法

等待,UI,和死锁!天啊!

采取以下代码:

    public MainPage()
    {
        this.InitializeComponent();

        step0();
        step1();
    }

    private async Task step0()
    {
        await Task.Delay(5000);
        System.Diagnostics.Debug.WriteLine("step 0");
    }

    private async Task step1()
    {
        await Task.Delay(3000);
        System.Diagnostics.Debug.WriteLine("step 1");
    }
}

如何确保始终在“步骤 1”之前打印“步骤 0”?使用Task.Wait会导致死锁。这是 Windows 应用商店应用

4

2 回答 2

8

您可以使用Task.ContinueWith将任务链接在一起,以便它们按顺序发生。

public MainPage()
{
    this.InitializeComponent();

    step0().ContinueWith(t => step1());
}

此外,阿列克谢的评论是正确的。 Task.Wait阻塞UI 线程。死锁是另一回事。

于 2012-11-16T06:11:34.313 回答
5

你不能有一个async构造函数,句号。

所以无论你做什么,你都需要处理构造函数在没有完成async初始化的情况下返回的情况。

有几种处理方法。如果“步骤”正在加载资源,那么您可以执行以下操作(使用AsyncLazy我的博客Stephen Toub 的博客或我的AsyncEx 库中的类型——它们几乎相同):

private readonly AsyncLazy<MyResource> resource;

public MainPage()
{
  resource = new AsyncLazy<MyResource>(async () =>
  {
    var a = await step0();
    var b = await step1();
    return new MyResource(a, b); // or whatever
  });
  resource.Start(); // start step0
}

public async Task MethodThatNeedsResource()
{
  var r = await resource; // ensure step1 is complete before continuing
}

也可以使用async void方法 或来执行此操作ContinueWith,但您必须仔细考虑使用这些方法进行错误处理。

  • AsyncLazy方法将捕获错误并在await resource执行时引发错误。
  • async void方法将立即向SynchronizationContext.
  • 天真的ContinueWith方法会默默地忽略所有错误。

无论您采用哪种方法,我都建议在 UI 中通知初始化正在进行中。(顺便说一句,我认为所有这些都应该进入 ViewModel 或 Model 类而不是MainPage)。

于 2012-11-16T13:50:28.890 回答