我正在查看某人的异步示例代码,并注意到其实现方式存在一些问题.在查看代码时,我想知道使用并行方式遍历列表是否比正常地遍历列表更有效.
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关键字一起使用?
发布评论