Thread t = new Thread(DoSomething); // Start the thread t.Start(); // Request that oThread be stopped t.Abort(); // Wait until oThread finishes. Join also has overloads // that take a millisecond interval or a TimeSpan object. t.Join(); //This will throw ThreadStateException since aborted threads cannot be restarted oThread.Start();The above approch is good for jobs which are going to be relatively long running
Issues
1. Spinning up a new thread and tearing one down are relatively costly actions, especially if compared to the cost of a small work being performed in the thread
2. Oversubscription is another issue. If too many threads are running, we’d have two components each fighting for the machine’s resources, forcing the operating system to spend more time context switching between components. Context switching is expensive for a variety of reasons, including the need to persist details of a thread’s execution prior to the operating system context switching out the thread and replacing it with another.
ThreadPool
.NET Framework maintains a pool of threads that service work items provided to it. The main method for doing this is the static QueueUserWorkItem
using (ManualResetEvent mre = new ManualResetEvent(false)) { ThreadPool.QueueUserWorkItem(delegate{DoSomething();}); ThreadPool.QueueUserWorkItem(delegate{DoSomethingelse();}); ThreadPool.QueueUserWorkItem(delegate{DoSomeMore();}); // Wait for all threads to complete. mre.WaitOne(1000000); }1. So no overhead of thread creation and tear down.
2. Minimizes the possibility of oversubscription.
3. Once your machine is sufficiently busy, the threadpool will queue up requests rather than immediately spawn more threads.
Issues
1. There is a limited number of threads in the .Net Thread Pool (250 per CPU by default), and they are being used by many of the .Net framework classes (e.g. timer events are fired on thread pool threads) so you wouldn’t want your application to hog the thread pool.
2. You cannot set the priority.
.Net 4.0
Parallel programming become much easier with the release of .Net 4.0 System.Threading.Tasks.Parallel
ParallelLoopResult loopResult = Parallel.For(0, 100, (y,loopState) => { Console.WriteLine("This is " + y); //The other option is Break which gurantees that all the iterations till the breaking iterations are completed if(y > 20) loopState.Stop(); if(loopState.IsStopped) Console.WriteLine("Loop was stopped while I am processing this"); }); Console.WriteLine("Ran to completion: " + loopResult.IsCompleted);
CancellationTokenSource cts = new CancellationTokenSource(); var options = new ParallelOptions { CancellationToken = cts.Token }; Task.Factory.StartNew(() => { Thread.Sleep(3000); cts.Cancel(); }); try { Parallel.For(0, 10000, options, (y, loopState) => { Thread.Sleep(1000); options.CancellationToken.ThrowIfCancellationRequested(); Console.WriteLine("This is " + y); }); } catch (OperationCanceledException e) { Console.WriteLine(e.Message); }
VERY SMALL LOOP BODIES
As previously mentioned, the Parallel class is implemented in a manner so as to provide for quality load balancing while incurring as little overhead as possible. There is still overhead, though. The overhead incurred by Parallel.For is largely centered around two costs:
1) Delegate invocations - Invoking a delegate incurs approximately the same amount of cost as a virtual method call.
2) Synchronization between threads for load balancing.
Tasktask1 = Task .Factory.StartNew(() => DoSomething(par1)); Task task2 = Task .Factory.StartNew(() => DoSomething(par2)); Task[] tasks = new Task[] {task1, task2}; Task.WaitAll(tasks); Parallel.Invoke( () => DoSomething("1"),()=>DoSomething("1"));
Reference
http://www.microsoft.com/download/en/details.aspx?id=19222
No comments:
Post a Comment