Here is a console program want 10 threads start in batch, wait 5 seconds, and stop in batch.
static void Main(string[] args)
{
System.Threading.Tasks.Parallel.For(0, 10, (index) =>
{
Action<int> act = (i) =>
{
Console.Write("start {0} ", i);
Thread.Sleep(5000);
};
act.BeginInvoke(index, OnTaskComplete, index);
});
Console.ReadKey();
}
static void OnTaskComplete(IAsyncResult res)
{
Console.Write("finish {0} ", res.AsyncState);
}
but the result is not what I expected, 10 threads start one-by-one SLOWLY(around 1 second interval), even some "finish" comes out before some "start".
when comment out Thread.Sleep, all threads start and finish in flash.
Does Thread.Sleep
affect other threads? Is there anyway to make a pure idle time?
/-----------------------------edit-----------------------------
same problem also happen in:
static void Main(string[] args)
{
System.Threading.Tasks.Parallel.For(0, 10, (index) =>
{
Console.Write("start {0} ", index);
Thread.Sleep(5000);
Console.Write("fnish {0} ", index);
});
Console.ReadKey();
}
----------------------Edit------------------------
finally I found a lovely way to substitute thread.sleep
static void Main(string[] args)
{
System.Threading.Tasks.Parallel.For(0, 10, (index) =>
{
Console.Write("start {0} ", index);
var t1 = new System.Threading.Timer(new TimerCallback(MyTimerCallback), index, 5000, 0);
});
Console.ReadKey();
}
static void MyTimerCallback(object o)
{
Console.Write("Timer callbacked ");
}
Sleep method causes the current thread to immediately block for the number of milliseconds or the time interval you pass to the method, and yields the remainder of its time slice to another thread. Once that interval elapses, the sleeping thread resumes execution. One thread cannot call Thread. Sleep on another thread.
sleep() blocks the main UI thread [closed] Save this question. Show activity on this post.
Thread. sleep causes the current thread to suspend execution for a specified period. This is an efficient means of making processor time available to the other threads of an application or other applications that might be running on a computer system.
Using Thread. sleep() frequently in an automation framework is not a good practice. If the applied sleep is of 5 secs and the web element is displayed in 2 secs only, the extra 3 secs will increase the execution time. And if you use it more often in the framework, the execution time would increase drastically.
This is by design. You are seeing the threadpool manager trying to keep a limited number of threads in the executing state. Important to ensure that your program isn't running more threads than your machine has cpu cores. That's inefficient, less work gets done when Windows is forced to start swapping the cores between active threads. The threadpool manager isn't smart enough to know that the thread is sleeping and not actually performing any work.
On a dual-core machine, you'll see the first 2 threads starting right away. Then additional threads are allowed to run, one by one with a one second interval when the thread manager notices that the active threads are not making any progress and are probably blocked. The order in which threads are released and execute the Console.Write() call is not deterministic.
This is an artificial test of course, real threads don't sleep. If you have threads that block for a long time, waiting for an I/O request to complete for example then using threadpool threads (tasks) is not the best solution.
TaskCreationOptions.LongRunning
will 'remove' the ThreadPool limitation.
I don't know the easy way to specify TaskCreationOptions.LongRunning
for Parallel.For
.
However, you can achieve the same effect using Task class:
Action<int> action = i =>
{
Console.Write("start {0} ", i);
Thread.Sleep(5000);
Console.Write("finish {0} ", i);
};
var tasks = Enumerable.Range(0, 100)
.Select(arg => Task.Factory.StartNew(() => action(arg), TaskCreationOptions.LongRunning))
.ToArray();
Task.WaitAll(tasks);
Without TaskCreationOptions.LongRunning
it will run exactly the same way as your Parallel.For
did.
I updated the code slightly to show the ThreadID when writing to the Console:
Console.WriteLine("start index:{0} thread id:{1} Time:{2} ", index, Thread.CurrentThread.ManagedThreadId.ToString(), DateTime.Now.ToLongTimeString());
Thread.Sleep(5000);
ConsoleWriteLine("finish index:{0} thread id:{1} Time:{2} ", index, Thread.CurrentThread.ManagedThreadId.ToString(), DateTime.Now.ToLongTimeString());
My machine is a dual core, here's the output I get. This should give you a sense of what's happening. Remember, the loop may not always run in order, i.e.. 0 to 9, being parallel, it grabs a chunk of your array and runs each item through the lambda.
Output:
start index:1 thread id:11 Time:11:07:17 PM
start index:0 thread id:9 Time:11:07:17 PM
start index:5 thread id:10 Time:11:07:17 PM
start index:6 thread id:12 Time:11:07:18 PM
start index:2 thread id:13 Time:11:07:19 PM
start index:7 thread id:14 Time:11:07:20 PM
start index:3 thread id:15 Time:11:07:21 PM
start index:8 thread id:16 Time:11:07:22 PM
finish index:0 thread id:9 Time:11:07:22 PM
start index:4 thread id:9 Time:11:07:22 PM
finish index:1 thread id:11 Time:11:07:22 PM
start index:9 thread id:11 Time:11:07:22 PM
finish index:5 thread id:10 Time:11:07:22 PM
finish index:6 thread id:12 Time:11:07:23 PM
finish index:2 thread id:13 Time:11:07:24 PM
finish index:7 thread id:14 Time:11:07:25 PM
finish index:3 thread id:15 Time:11:07:26 PM
finish index:8 thread id:16 Time:11:07:27 PM
finish index:4 thread id:9 Time:11:07:27 PM
finish index:9 thread id:11 Time:11:07:27 PM
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With