Parallel vs Await vs Result - 哪个更适合延迟执行

Posted

技术标签:

【中文标题】Parallel vs Await vs Result - 哪个更适合延迟执行【英文标题】:Parallel vs Await vs Result - which one is better for deferred execution 【发布时间】:2019-02-05 00:55:41 【问题描述】:

实现 #1 - 使用并行循环

var client = new HttpClient();
var processes = new List<Task<object>>();

Parallel.ForEach(urls, url =>

  processes.Add(client.GetAsync(url).Result.Content.ReadAsAsync<object>());
);

Task.WhenAll(processes);

实现#2 - 使用异步方法+结果

var client = new HttpClient();
var processes = new List<Task<object>>();

urls.ForEach(url =>

  processes.Add(GetChain(client, url));
);

Task.WhenAll(processes);

async Task<object> GetChain(HttpClient client, string url)

  return await client.GetAsync(url).Result.Content.ReadAsAsync<object>();

实现 #3 - 使用异步方法 + 等待

var client = new HttpClient();
var processes = new List<Task<object>>();

urls.ForEach(url =>

  processes.Add(GetChain(client, url));
);

Task.WhenAll(processes);

async Task<object> GetChain(HttpClient client, string url)

  var chain = await client.GetAsync(url);
  return await chain.Content.ReadAsAsync<object>();

我喜欢使用 Parallel 循环的实现 #1,但有一个 possibility Parallel 将在每次迭代时创建一个新线程并消耗更多资源。

问题

    这些方法之间有区别吗,我可以继续使用 Parallel.ForEach 吗? 如果并行循环不好,如何在不创建单独的“异步”方法的情况下改进它? “await method.Result”是否与“await method1 await method2”相同,#2 vs #3?

附:有两个“等待”调用,因为 HttpClient 请求数据,然后异步读取。

额外的问题 - 这些行是否相同?

method1.Result.method2                             // get result immediately
method1.ContinueWith(data => data.Result.method2)  // call both methods first

【问题讨论】:

只有在执行一些繁重的并行操作时才使用 Parallel.foreach 有用。将项目添加到列表中并不繁重。混合使用异步和并行是没有用的。 第一个 (Parallel.ForEach()) 只是增加了一个无用的并行级别。填写任务应该是轻量级和快速的。 额外:不一样。但我猜你可能想要一个延续。 示例 2 中的 .Result 杀死了 async/await 的一个分支,甚至可能导致死锁。 另外,List&lt;T&gt; 不是线程安全的,不能像示例 1 中那样使用。 【参考方案1】:

考虑以下示例。它可以帮助您找到问题的答案:

private static readonly List<Uri> Urls = new List<Uri>() 
    new Uri(""),
    new Uri("") ;
....
Stopwatch stopwatch = new Stopwatch();
stopwatch.Start();
var result1 = Urls.Select(GetContent).ToArray();
stopwatch.Stop();
Console.WriteLine($@"Synchronous and NOT In Parallel:stopwatch.ElapsedMilliseconds");

stopwatch.Restart();
var result2 = Urls.AsParallel().Select(GetContent).ToArray();
stopwatch.Stop();
Console.WriteLine($@"Synchronous and In Parallel:stopwatch.ElapsedMilliseconds");

stopwatch.Restart();
var task1 = DoAsyncNotParallel();
task1.Wait();
stopwatch.Stop();
Console.WriteLine($@"Asynchronous and NOT In Parallel:stopwatch.ElapsedMilliseconds");

stopwatch.Restart();
var task2 = DoAsyncInParallel();
task2.Wait();
stopwatch.Stop();
Console.WriteLine($@"Asynchronous and In Parallel:stopwatch.ElapsedMilliseconds");

static async Task<string[]> DoAsyncNotParallel()

    List<string> content = new List<string>();
    foreach (var uri in Urls)
    
        content.Add(await GetContentAsync(uri));
    

    return content.ToArray();


static async Task<string[]> DoAsyncInParallel()

    var tasks = Urls.Select(uri => GetContentAsync(uri));

    var content = await Task.WhenAll(tasks);

    return content;

private static async Task<string> GetContentAsync(Uri uri)

    HttpClient httpClient = new HttpClient();
    var response = await httpClient.GetAsync(uri);
    var content = await response.Content.ReadAsStringAsync();
    return content;



private static string GetContent(Uri uri)

    HttpClient httpClient = new HttpClient();
    var response = httpClient.GetAsync(uri).Result;
    var content = response.Content.ReadAsStringAsync().Result;
    return content;

我建议您浏览以下对您有用的链接:

    Async Programming : Introduction to Async/Await on ASP.NET,作者 斯蒂芬·克利里 How and Where Concurrent Asynchronous I/O with ASP.NET Web API,作者 Tugberk Ugurlu Parallel Programming with .NET,来自微软

关于问题的最后一部分:

method1.Result.method2();  

调用线程被阻塞,直到method1完成,然后method2被调用

method1.ContinueWith(data => data.Result.method2());

调用线程未被阻塞,method1正在异步执行。 一旦 method1 完成,新任务就会像 Task.Run(()=> method1.Result.method2()) 一样运行。在这种情况下,method1.Result 不会阻塞调用线程,因为 method1 已经完成,isCompleted=true

【讨论】:

以上是关于Parallel vs Await vs Result - 哪个更适合延迟执行的主要内容,如果未能解决你的问题,请参考以下文章

callback vs async.js vs promise vs async / await

笑话:await vs setImmediate vs useFakeTimers vs new Promise(setImmediate)

异步 callback vs promise vs async/await

javascript Promise vs Async&Await

javascript [JS] Promise VS Async / Await

javascript [JS] Promise VS Async / Await