繁体   English   中英

Parallel.Invoke不等待异步方法完成

[英]Parallel.Invoke does not wait for async methods to complete

我有一个应用程序,可以从不同来源提取大量数据。 本地数据库,网络数据库和Web查询。 所有这些都可能需要几秒钟才能完成。 因此,首先我决定并行运行它们:

Parallel.Invoke(
   () => dataX = loadX(),
   () => dataY = loadY(),
   () => dataZ = loadZ()
);

不出所料,这三个都是并行执行的,但是直到最后一个完成后,整个块的执行才会返回。

接下来,我决定向应用程序添加一个微调器或“忙碌指示器”。 我不想阻止UI线程,否则微调器将不会旋转。 因此,这些需要在async模式下运行。 但是,如果我以异步模式运行所有这三个组件,那么它们的影响会“同步”发生,只是不在与UI相同的线程中。 我仍然希望它们平行运行。

spinner.IsBusy = true;

Parallel.Invoke(
     async () => dataX = await Task.Run(() => { return loadX(); }),
     async () => dataY = await Task.Run(() => { return loadY(); }),
     async () => dataZ = await Task.Run(() => { return loadZ(); })
);

spinner.isBusy = false;

现在,Parallel.Invoke不再等待方法完成,微调器立即关闭。 更糟糕的是,dataX / Y / Z为空,并且以后会发生异常。

这里正确的方法是什么? 我应该改用BackgroundWorker吗? 我希望利用.Net 4.5功能。

听起来您确实想要这样的东西:

spinner.IsBusy = true;
try
{
    Task t1 = Task.Run(() => dataX = loadX());
    Task t2 = Task.Run(() => dataY = loadY());
    Task t3 = Task.Run(() => dataZ = loadZ());

    await Task.WhenAll(t1, t2, t3);
}
finally
{
    spinner.IsBusy = false;
}

这样,您就异步地等待所有任务完成( Task.WhenAll返回一个在其他所有任务完成时完成的任务),而不会阻塞UI线程...而Parallel.Invoke (和Parallel.ForEach等)是阻止调用,并且不应在UI线程中使用。

Parallel.Invoke不会被异步lambda阻塞的原因是它只是在等待每个Action返回...这基本上是在等待开始时。通常,您需要分配一个异步lambda到Func<Task>或类似的方法,就像您通常不想编写async void方法一样。)

如您在问题中所述,您的两个方法查询数据库(一个方法通过sql,另一个方法通过azure),第三个方法触发对Web服务的POST请求。 所有这三种方法都在进行I / O绑定工作

调用Parallel.Invoke时发生的事情是,您基本上触发了三个ThreadPool线程来阻塞并等待基于I / O的操作完成,这非常浪费资源,并且在需要时会严重扩展。

取而代之的是,您可以使用异步API,它们三个都公开:

  1. 通过Entity Framework 6或ADO.NET的SQL Server
  2. Azure具有异步API
  3. 通过HttpClient.PostAsync Web请求

让我们假设以下方法:

LoadXAsync();
LoadYAsync();
LoadZAsync();

您可以这样称呼他们:

spinner.IsBusy = true;
try
{
    Task t1 = LoadXAsync();
    Task t2 = LoadYAsync();
    Task t3 = LoadZAsync();

    await Task.WhenAll(t1, t2, t3);
}
finally
{
    spinner.IsBusy = false;
}

这将具有相同的预期结果。 它不会冻结您的UI,它将使您节省宝贵的资源。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM