【问题标题】:using Parallel.ForEach with/or async/await使用 Parallel.ForEach 和/或 async/await
【发布时间】:2015-09-09 12:06:28
【问题描述】:

我尝试验证我的图片 URL 以查看它们是否有效。我有这么多,完成这项任务需要几个小时。因此,我决定异步进行。我想知道按照以下方式执行我的代码是否有任何重大差异或优势。

我的主要职能是:

Async Function testUrl_async(ByVal myImageurl As String) As Task(Of Boolean)

   myHttpResponse = Await myHttpClient.GetAsync(myImageurl)
    If myHttpResponse.IsSuccessStatusCode Then
        mySuccess = True
    Else
        mySuccess = False
    End If

    Return mySuccess
End Function

 Function testUrl(ByVal myImageurl As String) As  Boolean

   myHttpResponse = myHttpClient.GetAsync(myImageurl)
    If myHttpResponse.IsSuccessStatusCode Then
        mySuccess = True
    Else
        mySuccess = False
    End If

    Return mySuccess
End Function

1) 使用异步等待。

For Each myImage In myImages
    Dim result=await testUrl_async(myImageUrl).Result 
    'some code                  
Next

2) 使用并行 foreach

Parallel.ForEach(myImages, 
    Sub(myImage)
        testUrl(pictureComponent.websiteShop.hqpatronen, myImageUrl) 
        'some code
    End Sub)

3) 使用并行 foreach 和 asnyc/await

Parallel.ForEach(myImages, 
    Sub(myImage)
        await testUrl_async(pictureComponent.websiteShop.hqpatronen, myImageUrl) 
    'some code
    End Sub)

第三个可能是最好的解决方案,但它不允许我在ForEach 中调用Await/Async。

如果我使用第二个,testurl 函数有异步 http 调用,但没有 Await,因此它崩溃并显示异常消息:

[TaskCanceledException: 任务被取消。]

在呼叫myHttpClient.GetAsync 的线路上。我猜它会抛出这个异常,因为ForEach 已经结束并且请求取消但 httpclient 还没有完成它的工作。如果这可能是最好的解决方案,我该如何处理?

或者任何其他可以让我的工作更快的解决方案。

【问题讨论】:

  • 这对于 TPL Dataflow 来说可能是一项不错的任务,它提供了粗略的 Parallel.ForEach 功能并支持异步。
  • 它是新的并且仅受 4.5 及更高版本支持?
  • @batmaci 就像async/await,是的
  • @PanagiotisKanavos 关键字是 C# 的一部分,而不是框架。添加的所有兼容性包都是关键字工作所必需的框架位。
  • @CoryNelson 不完全是,因为async/await 不需要任何额外的 IL。即使在 C# 5 中,编译器也会生成一个状态机来处理等待。这就是为什么需要Microsoft.Build 的原因——它实际上改变了项目的构建方式。兼容性包不会修改运行时本身,也不会添加任何新的 IL。

标签: vb.net async-await task-parallel-library parallel.foreach


【解决方案1】:

您当然不想使用Parallel.ForEach。 Parallel 用于将受 CPU 限制的算法传播到多个内核上,这不会给您带来任何好处(在您的场景中,您的算法不受 CPU 限制)。

您真正想要的是并发,而不是并行。异步并发可以使用Task.WhenAll:

Dim tasks = myImages.Select(Function(x) testUrl_async(x))
Dim results = Await Task.WhenAll(tasks)

【讨论】:

  • 我的第一种方法与经典的每个方法和同步等待之间是否存在很大的性能(速度)差异?
  • 我进行了测试,结果有很大不同。谢谢你的帮助:)
  • 你能看看我下面的另一个帖子,它确实与这个帖子有关吗?我不想问更多问题,而是创建了一个新帖子。 stackoverflow.com/questions/31027885/…
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-01-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-09-12
  • 2012-03-02
相关资源
最近更新 更多