繁体   English   中英

强制Parallel.ForEach为集合中的每个项目创建一个线程

[英]Force Parallel.ForEach make one thread per item in collection

这是我使用的代码示例:

        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()

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM