【发布时间】:2018-05-16 01:59:47
【问题描述】:
我正在查看某人的异步示例代码,并注意到它的实现方式存在一些问题。在查看代码时,我想知道使用 as 并行循环遍历列表是否比正常循环遍历列表更有效。
据我所知,性能差异很小,两者都用尽了每个处理器,并且都在相同的时间内完成。
这是第一种方法
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);
}
}
}
【问题讨论】:
-
他们完成了多少时间?
-
RunCode1() 耗时 23244 毫秒,RunCode2() 耗时 23219 毫秒。我有 4 个核心,所以这比我预期的要快一点,但我认为两者之间的时间相当微不足道。
-
它们非常接近,但我认为如果您在更多客户端(数千个)上尝试它或在
Initialize中添加更长的延迟,您将开始看到差异。 (使用Thread.Sleep(time);而不是所有秒表代码) -
有趣的是,这对时代产生了巨大的影响。 RunCode1() 现在需要 12016,而 RunCode2() 现在需要 6019。
标签: c# asynchronous