使用 Parallel.ForEach with/or async/await
using Parallel.ForEach with/or async/await
我尝试验证我的图片 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: A task was canceled.]
在调用 myHttpClient.GetAsync
的行上。我猜它抛出这个异常是因为 ForEach
已经结束并且请求取消但是 httpclient 还没有完成它的工作。如果这是最好的解决方案,我该如何处理?
或者可以让我的工作更快的任何其他解决方案。
你肯定不想使用Parallel.ForEach
。 Parallel
用于在多个内核上传播 CPU 绑定算法,这不会给您带来任何好处(在您的场景中,您的算法不是 CPU 绑定)。
你真正想要的是并发,而不是并行。异步并发可以使用Task.WhenAll
:
来完成
Dim tasks = myImages.Select(Function(x) testUrl_async(x))
Dim results = Await Task.WhenAll(tasks)
我尝试验证我的图片 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: A task was canceled.]
在调用 myHttpClient.GetAsync
的行上。我猜它抛出这个异常是因为 ForEach
已经结束并且请求取消但是 httpclient 还没有完成它的工作。如果这是最好的解决方案,我该如何处理?
或者可以让我的工作更快的任何其他解决方案。
你肯定不想使用Parallel.ForEach
。 Parallel
用于在多个内核上传播 CPU 绑定算法,这不会给您带来任何好处(在您的场景中,您的算法不是 CPU 绑定)。
你真正想要的是并发,而不是并行。异步并发可以使用Task.WhenAll
:
Dim tasks = myImages.Select(Function(x) testUrl_async(x))
Dim results = Await Task.WhenAll(tasks)