如何将AsParallel与async和await关键字一起使用? [英] How do you use AsParallel with the async and await keywords?
问题描述
我正在查看某人的异步示例代码,并注意到其实现方式存在一些问题.在查看代码时,我想知道使用并行方式遍历列表是否比正常地遍历列表更有效.
I was looking at someone sample code for async and noticed a few issues with the way it was implemented. Whilst looking at the code I wondered if it would be more efficient to loop through a list using as parallel, rather than just looping through the list normally.
据我所知,性能几乎没有差别,它们都用尽了每个处理器,并且都花了相同的时间来完成.
As far as I can tell there is very little difference in performance, both use up every processor, and both talk around the same amount of time to completed.
这是第一种方法
var tasks= Client.GetClients().Select(async p => await p.Initialize());
这是第二个
var tasks = Client.GetClients().AsParallel().Select(async p => await p.Initialize());
我能正确假设两者之间没有区别吗?
Am I correct in assuming there is no difference between the two?
完整程序可在下面找到
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApplication2
{
class Program
{
static void Main(string[] args)
{
RunCode1();
Console.WriteLine("Here");
Console.ReadLine();
RunCode2();
Console.WriteLine("Here");
Console.ReadLine();
}
private async static void RunCode1()
{
Stopwatch myStopWatch = new Stopwatch();
myStopWatch.Start();
var tasks= Client.GetClients().Select(async p => await p.Initialize());
Task.WaitAll(tasks.ToArray());
Console.WriteLine("Time ellapsed(ms): " + myStopWatch.ElapsedMilliseconds);
myStopWatch.Stop();
}
private async static void RunCode2()
{
Stopwatch myStopWatch = new Stopwatch();
myStopWatch.Start();
var tasks = Client.GetClients().AsParallel().Select(async p => await p.Initialize());
Task.WaitAll(tasks.ToArray());
Console.WriteLine("Time ellapsed(ms): " + myStopWatch.ElapsedMilliseconds);
myStopWatch.Stop();
}
}
class Client
{
public static IEnumerable<Client> GetClients()
{
for (int i = 0; i < 100; i++)
{
yield return new Client() { Id = Guid.NewGuid() };
}
}
public Guid Id { get; set; }
//This method has to be called before you use a client
//For the sample, I don't put it on the constructor
public async Task Initialize()
{
await Task.Factory.StartNew(() =>
{
Stopwatch timer = new Stopwatch();
timer.Start();
while(timer.ElapsedMilliseconds<1000)
{}
timer.Stop();
});
Console.WriteLine("Completed: " + Id);
}
}
}
推荐答案
区别应该很小.
在您的第一种情况下:
var tasks = Client.GetClients().Select(async p => await p.Initialize());
执行线程将(一次一个)开始为客户端列表中的每个元素执行Initialize
. Initialize
立即将方法排队到线程池中,并返回未完成的Task
.
The executing thread will (one at a time) start executing Initialize
for each element in the client list. Initialize
immediately queues a method to the thread pool and returns an uncompleted Task
.
在第二种情况下:
var tasks = Client.GetClients().AsParallel().Select(async p => await p.Initialize());
执行线程将派生到线程池,并(并行)开始为客户端列表中的每个元素执行Initialize
. Initialize
具有相同的行为:它立即将方法排队到线程池中并返回.
The executing thread will fork to the thread pool and (in parallel) start executing Initialize
for each element in the client list. Initialize
has the same behavior: it immediately queues a method to the thread pool and returns.
这两个时间几乎相同,因为您只并行化了少量代码:将方法排队到线程池和返回未完成的Task
.
The two timings are nearly identical because you're only parallelizing a small amount of code: the queueing of the method to the thread pool and the return of an uncompleted Task
.
如果Initialize
在其第一个await
之前做了更长的工作(同步),则使用AsParallel
可能有意义.
If Initialize
did some longer (synchronous) work before its first await
, it may make sense to use AsParallel
.
请记住,所有async
方法(和lambda)都开始被同步执行(请参见我自己的简介).
Remember, all async
methods (and lambdas) start out being executed synchronously (see the official FAQ or my own intro post).
这篇关于如何将AsParallel与async和await关键字一起使用?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!