我正在查看某人的异步示例代码,并注意到其实现方式存在一些问题。在查看代码时,我想知道使用并行方式循环列表是否比正常循环列表更有效。
据我所知,性能上的差异非常小,两者都耗尽了每个处理器,并且完成时间都相同。
这是第一种方法
var tasks= Client.GetClients().Select(async p => await p.Initialize());
这是第二个
var tasks = Client.GetClients().AsParallel().Select(async p => await p.Initialize());
我假设两者之间没有区别是否正确?
完整的程序可以在下面找到
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
.
在你的第二种情况下:
var tasks = Client.GetClients().AsParallel().Select(async p => await p.Initialize());
执行线程将分叉到线程池并(并行)开始执行Initialize
对于客户端列表中的每个元素。Initialize
具有相同的行为:它立即将方法排队到线程池中并返回。
这两个时间几乎相同,因为您只并行化少量代码:将方法排队到线程池以及返回未完成的代码Task
.
If Initialize
在第一次之前做了一些较长的(同步)工作await
,使用可能有意义AsParallel
.
记住,所有async
方法(和 lambda)开始同步执行(请参阅官方常见问题解答 http://blogs.msdn.com/b/pfxteam/archive/2012/04/12/10293335.aspx or 我自己的介绍帖子 http://nitoprograms.blogspot.com/2012/02/async-and-await.html).
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)