如何在Windows Phone上运行并行任务?

时间:2013-11-29 14:53:11

标签: c# multithreading asynchronous windows-phone-8 parallel-processing

我正在构建一个WP8应用程序,我需要执行大约30个Web请求。这些请求不依赖于彼此,因此可以并行化。

我的代码看起来像这样(简化/伪代码):

foreach (Uri uri in uris)
{
    var rawData = await Task.Run(() => httpClient.GetStringAsync(uri).ConfigureAwait(false));

    var processedData = dataProcessor.Process(rawData);
    processedDataCollection.Add(processedData);
}

当我看到提琴手时,请求全部都是连续的;它需要几秒钟来执行和处理所有这些。但是,我不希望代码等到1个请求完成后才转移到下一个请求,我想同时执行多个请求。

通常我会使用Parallel.Invoke()Parallel.ForEach()或类似的东西来执行此操作,但显然并行库在Windows Phone 8中不可用。

那么实现这一目标的最佳方法是什么? Task.Factory.StartNew()new Thread()

2 个答案:

答案 0 :(得分:10)

无需在单独的线程上运行每个请求。您可以轻松地执行此操作:

var raw = await Task.WhenAll(uris.Select(uri => httpClient.GetStringAsync(uri)));
var processed = raw.Select(data => dataProcessor.Process(data)).ToArray();

此代码获取uris的集合,并为每个代码(Select(...))启动HTTP下载。然后它异步地等待它们全部完成(WhenAll)。然后在第二行代码中处理所有数据。

但是,Windows Phone运行时可能会限制您对同一服务器的最大请求数。

答案 1 :(得分:3)

您正在使用await来创建您创建的任务 - 这意味着您在继续该方法之前等待完成调用。正如您所指出的,您的foreach未并行化,因此您在此处所做的是许多串行请求。

您可以按照(可能)打算使用Task.WaitAll方法进行此操作。这样的事情就足够了:

var tasks = new List<Task>();

foreach (Uri uri in uris)
{
    var thisTask = Task.Run(() => 
                       { 
                         httpClient.GetStringAsync(uri).ConfigureAwait(false);
                         var processedData = dataProcessor.Process(rawData);
                         processedDataCollection.Add(processedData);
                       });

    tasks.Add(thisTask);
}

Task.WaitAll(tasks);

请注意,这也会平行处理您的数据(也就是说,它也会并行调用.Process),原始代码没有。

我还要补充一点,你可能想要一次运行30个请求,除非他们是不同的服务器。在同一台服务器上同时向Uris发出30个请求不太可能改善您的处理时间。 (幸运的是,TPL可能会为您解决这个问题,因为它会稍微限制并行性。)