Here is code sample I have used:
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);
So, as I thought it will give me 1 (or maybe 2, if we take in attention some overhead work) seconds, but it take 4 seconds. Does Parallel.ForEach takes threads from some prepared before thread pool or creates the new ones? How can I achieve 1-2 seconds work?
Threads are only really useful if your constraint is CPU. All you are doing is having lots of threads individually doing nothing, and doing nothing in parallel.
I would approach this a very different way. What you are doing now is:
I would turn it around:
At the simplest (pseudo-code):
WaitHandle[] handles = ... start all the async tasks...
Thread.Sleep(1000);
foreach(handle)
handle.WaitOne(0) ... log result
But possibly something involving:
WaitHandle[] handles = ... start all the async tasks...
System.Threading.WaitHandle.WaitAll(handles, 1000);
foreach(handle ...)
handle.WaitOne(0) ... log result
Also: you might consider replacing new Exception("By timeout")
with new TimeoutException()
.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.