Force Parallel.ForEach为集合中的每个项目生成一个线程
本文关键字:线程 一个 项目 Force ForEach 集合 Parallel | 更新日期: 2023-09-27 18:24:33
以下是我使用的代码示例:
Stopwatch s = new Stopwatch();
s.Start();
ParallelOptions po = new ParallelOptions();
// hosts contain 23 items
po.MaxDegreeOfParallelism = hosts.Count();
Parallel.ForEach(hosts, po, p =>
{
using (TcpClient tcpClient = new TcpClient())
{
IAsyncResult result = tcpClient.BeginConnect(p.Value, 80, null, null);
WaitHandle timeoutHandler = result.AsyncWaitHandle;
try
{
if (!result.AsyncWaitHandle.WaitOne(1000, false))
{
tasks.TryAdd(p.Key, new TaskCompleteResult { result = false, exc = new Exception("By timeout") });
tcpClient.Close();
}
else
{
tasks.TryAdd(p.Key, new TaskCompleteResult { result = true, exc = null });
}
tcpClient.EndConnect(result);
}
catch (Exception ex)
{
tasks.TryAdd(p.Key, new TaskCompleteResult { result = false, exc = ex });
}
finally
{
timeoutHandler.Close();
}
}
});
s.Stop();
Console.WriteLine(s.Elapsed.TotalSeconds);
所以,正如我所想,它会给我1秒(或者可能2秒,如果我们注意一些开销),但它需要4秒。Parallel.ForEach是从一些预先准备好的线程池中获取线程还是创建新的线程?我怎样才能完成1-2秒的工作?
只有当您的约束是CPU时,线程才真正有用。你所做的只是让很多线程单独什么都不做,什么都不并行。
我会用一种非常不同的方式来处理这个问题。你现在正在做的是:
- 创建大量线程
- 每个都创建一个等待句柄,然后阻塞长达1秒
我会扭转局面:
- 创建大量等待句柄
- 然后开始阻塞剩余的一秒钟
最简单的(伪代码):
WaitHandle[] handles = ... start all the async tasks...
Thread.Sleep(1000);
foreach(handle)
handle.WaitOne(0) ... log result
但可能涉及到:
WaitHandle[] handles = ... start all the async tasks...
System.Threading.WaitHandle.WaitAll(handles, 1000);
foreach(handle ...)
handle.WaitOne(0) ... log result
另外:您可以考虑将new Exception("By timeout")
替换为new TimeoutException()
。