如何在Windows Phone上运行并行任务?
我正在构建一个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); }
当我看到Fiddler时,请求全部都是sequantial; 它需要几秒钟来执行和处理所有这些。 但是,我不希望代码等到1个请求完成后才转移到下一个请求,我想同时执行多个请求。
通常我会使用Parallel.Invoke()
或Parallel.ForEach()
或类似的东西来执行此操作,但显然并行库在Windows Phone 8中不可用。
那么实现这一目标的最佳方法是什么? Task.Factory.StartNew()
? new Thread()
?
无需在单独的线程上运行每个请求。 您可以轻松地执行此操作:
var raw = await Task.WhenAll(uris.Select(uri => httpClient.GetStringAsync(uri))); var processed = raw.Select(data => dataProcessor.Process(data)).ToArray();
此代码获取uris
的集合并为每个代码启动HTTP下载( Select(...)
)。 然后它异步地等待它们全部完成( WhenAll
)。 然后在第二行代码中处理所有数据。
但是,Windows Phone运行时可能会限制您对同一服务器的最大请求数。
您正在使用await
您创建的任务 – 这意味着您在继续该方法之前等待调用完成。 正如你所指出的那样,你的foreach
没有并行化,所以你在这里做的是一些串行请求。
您可以(可能)打算使用Task.WaitAll
方法进行此运行。 这样的东西应该足够了:
var tasks = new List(); 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可能会为您解决这个问题,因为它会稍微限制并行性。)