使用 "Task.WhenAll" 时如何控制线程数
How can I control thread count when I use "Task.WhenAll"
我正在通过异步发出 http get 请求来验证图像 url。下面的代码一切正常,但是当我有这么多图像时,我们的防火墙将阻止我的互联网访问,因为有太多线程同时请求。因此,我一直在寻找一种解决方案,如何限制并发 运行 线程的数量。我最终得到了这个 thread telling me to use SemaphoreSlim 但我不知何故无法理解这个想法以及如何实现它?
- 在添加任务时,SemaphoreSlim wait 或 waitAsnyc(到底有什么区别?)应该在 foreach 中吗?我可以像在代码中那样使用 linq 创建任务列表吗?
- 为什么要用task.Run?
- 线程从哪一行开始执行?在 task.run 或 task.whenall?
之后
如果这不是最佳方法,请提出更好的方法。我不确定将 MaxDegreeOfParallelism 与 parallel.foreach 一起使用是否也有意义?
Dim tasks = myImages.Select(Function(x) testUrl_async(x))
Dim results = Await Task.WhenAll(tasks)
Async Function testUrl_async(ByVal myImage As image) As Task(Of image)
Dim myImageurl as string=myImage.imageurl
myHttpResponse = Await myHttpClient.GetAsync(myImageurl)
If myHttpResponse.IsSuccessStatusCode Then
Return myImage
Else
Return Nothing
End If
End Function
我假设您不在 WPF 或 Windows 表单线程中。如果您在 await
.
之后将只有一个线程在工作
正如我们假设您不在这些线程中一样,ThreadPool
is used to execute the continuations after the await
. You can change the amount of Threads used by the pool with ThreadPool.SetMaxThreads
但我建议您不要那样做,让 .NET 来做正确的事情。这通常是最好的方法。
您可以像这样使用 Task
和 SemaphoreSlim
:
var MaxAllowedConcurrentRequestsCount = 20;
var guard = new SemaphoreSlim(0, MaxAllowedConcurrentRequestsCount);
foreach(var imageUrl in imageUrls)
{
guard.Wait()
var image = await Task.Factory.StartNew((imageUrl) => return myHttpClient.Get(imageUrl));
guard.Release();
// You can do whaterver you like with image. For example add it to you concurrent list.
}
our firewall will block my internet access because of so many threads concurrently requesting. Therefore I was looking for a solution how to restrict the count of concurrently running threads.
很确定防火墙正在限制您的 连接数 ,因此您想限制您的 连接数 (不是 线程).
is that SemaphoreSlim wait or waitAsnyc (what is the difference anyway?)
Wait
是同步等待 - 它会阻塞调用线程。 WaitAsync
是一个异步等待 - 它释放调用线程并在信号量可用时恢复执行当前方法。
should be inside a foreach while adding tasks? Can I just create the task list with linq as I do in my code?
您可以采用任何一种方式:显式构建列表,或使用 LINQ。
why is there used task.Run?
该答案有误。 Task.Run
在这里当然不需要或不需要。
after which line is executed does the thread start? after task.run or task.whenall?
当您调用 Task.Run
时,该委托立即排入线程池。但正如我上面所说,你不想使用 Task.Run
(它也不应该在原始答案中使用)。
所以,像这样的东西就足够了:
Private _mutex As New SemaphoreSlim(20)
Async Function testUrl_async(myImage As image) As Task(Of image)
Await _mutex.WaitAsync()
Try
Dim myImageurl = myImage.imageurl
Dim myHttpResponse = Await myHttpClient.GetAsync(myImageurl)
Return If(myHttpResponse.IsSuccessStatusCode, myImage, Nothing)
Finally
_mutex.Release()
End Try
End Function
我正在通过异步发出 http get 请求来验证图像 url。下面的代码一切正常,但是当我有这么多图像时,我们的防火墙将阻止我的互联网访问,因为有太多线程同时请求。因此,我一直在寻找一种解决方案,如何限制并发 运行 线程的数量。我最终得到了这个 thread telling me to use SemaphoreSlim 但我不知何故无法理解这个想法以及如何实现它?
- 在添加任务时,SemaphoreSlim wait 或 waitAsnyc(到底有什么区别?)应该在 foreach 中吗?我可以像在代码中那样使用 linq 创建任务列表吗?
- 为什么要用task.Run?
- 线程从哪一行开始执行?在 task.run 或 task.whenall? 之后
如果这不是最佳方法,请提出更好的方法。我不确定将 MaxDegreeOfParallelism 与 parallel.foreach 一起使用是否也有意义?
Dim tasks = myImages.Select(Function(x) testUrl_async(x))
Dim results = Await Task.WhenAll(tasks)
Async Function testUrl_async(ByVal myImage As image) As Task(Of image)
Dim myImageurl as string=myImage.imageurl
myHttpResponse = Await myHttpClient.GetAsync(myImageurl)
If myHttpResponse.IsSuccessStatusCode Then
Return myImage
Else
Return Nothing
End If
End Function
我假设您不在 WPF 或 Windows 表单线程中。如果您在 await
.
正如我们假设您不在这些线程中一样,ThreadPool
is used to execute the continuations after the await
. You can change the amount of Threads used by the pool with ThreadPool.SetMaxThreads
但我建议您不要那样做,让 .NET 来做正确的事情。这通常是最好的方法。
您可以像这样使用 Task
和 SemaphoreSlim
:
var MaxAllowedConcurrentRequestsCount = 20;
var guard = new SemaphoreSlim(0, MaxAllowedConcurrentRequestsCount);
foreach(var imageUrl in imageUrls)
{
guard.Wait()
var image = await Task.Factory.StartNew((imageUrl) => return myHttpClient.Get(imageUrl));
guard.Release();
// You can do whaterver you like with image. For example add it to you concurrent list.
}
our firewall will block my internet access because of so many threads concurrently requesting. Therefore I was looking for a solution how to restrict the count of concurrently running threads.
很确定防火墙正在限制您的 连接数 ,因此您想限制您的 连接数 (不是 线程).
is that SemaphoreSlim wait or waitAsnyc (what is the difference anyway?)
Wait
是同步等待 - 它会阻塞调用线程。 WaitAsync
是一个异步等待 - 它释放调用线程并在信号量可用时恢复执行当前方法。
should be inside a foreach while adding tasks? Can I just create the task list with linq as I do in my code?
您可以采用任何一种方式:显式构建列表,或使用 LINQ。
why is there used task.Run?
该答案有误。 Task.Run
在这里当然不需要或不需要。
after which line is executed does the thread start? after task.run or task.whenall?
当您调用 Task.Run
时,该委托立即排入线程池。但正如我上面所说,你不想使用 Task.Run
(它也不应该在原始答案中使用)。
所以,像这样的东西就足够了:
Private _mutex As New SemaphoreSlim(20)
Async Function testUrl_async(myImage As image) As Task(Of image)
Await _mutex.WaitAsync()
Try
Dim myImageurl = myImage.imageurl
Dim myHttpResponse = Await myHttpClient.GetAsync(myImageurl)
Return If(myHttpResponse.IsSuccessStatusCode, myImage, Nothing)
Finally
_mutex.Release()
End Try
End Function