Parallel.Invoke不会等待异步方法完成 [英] Parallel.Invoke does not wait for async methods to complete

查看:244
本文介绍了Parallel.Invoke不会等待异步方法完成的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有拉从不同来源的数据相当数量的应用程序。本地数据库,联网数据库和网络查询。所有这些可能需要几秒钟才能完成。因此,首先,我决定来运行这些并行:

I have an application that pulls a fair amount of data from different sources. A local database, a networked database, and a web query. Any of these can take a few seconds to complete. So, first I decided to run these in parallel:

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

正如预期的那样,所有这三个并行执行,但整个块上执行不回来直到最后一个人完成的。

As expected, all three execute in parallel, but execution on the whole block doesn't come back until the last one is done.

接下来,我决定一个微调或忙指示器添加到应用程序。我不想阻止用户界面线程或微调不再打滑。因此,这些需要在异步模式下运行。但是,如果我在异步模式下运行的所有三个,那么他们影响到同步发生,只是没有在同一个线程的用户界面。我还是希望他们奔着水货。

Next, I decided to add a spinner or "busy indicator" to the application. I don't want to block the UI thread or the spinner won't spin. So these need to be ran in async mode. But if I run all three in an async mode, then they in affect happen "synchronously", just not in the same thread as the UI. I still want them ran parallel.

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不等待的方法来完成,并微调是立即关闭。更糟的是,数据X / Y / Z是空的,后来发生的异常。

Now, the Parallel.Invoke does not wait for the methods to finish and the spinner is instantly off. Worse, dataX/Y/Z are null and exceptions occur later.

什么是这里的正确方法?我应该使用一个BackgroundWorker呢?我希望使用的.NET 4.5的功能。

What's the proper way here? Should I use a BackgroundWorker instead? I was hoping to make use of the .Net 4.5 features.

推荐答案

这听起来像你真正想要的东西,如:

It sounds like you really want something like:

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;
}

你的这样异步的等待所有任务完成(<一个href=\"http://msdn.microsoft.com/en-us/library/system.threading.tasks.task.whenall%28v=vs.110%29.aspx\"><$c$c>Task.WhenAll返回其完成时所有其他任务完成),而不会阻塞UI线程...而 Parallel.Invoke (和 Parallel.ForEach <任务/ code>等)是的拦截的通话,不应该在UI线程中使用。

That way you're asynchronously waiting for all the tasks to complete (Task.WhenAll returns a task which completes when all the other tasks complete), without blocking the UI thread... whereas Parallel.Invoke (and Parallel.ForEach etc) are blocking calls, and shouldn't be used in the UI thread.

(即 Parallel.Invoke 不是你的异步lambda表达式阻塞的原因是,它只是在等待,直到每个动作返回...这基本上是当它击中的启动的的的await的通常你会希望一个异步的lambda分配给 Func键&LT;任务&GT; 或类似的,在你不想平时写异步无效方法是一样的。)

(The reason that Parallel.Invoke wasn't blocking with your async lambdas is that it was just waiting until each Action returned... which was basically when it hit the start of the await. Normally you'd want to assign an async lambda to Func<Task> or similar, in the same way that you don't want to write async void methods usually.)

这篇关于Parallel.Invoke不会等待异步方法完成的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆