In C# is there any difference between using a delegate to do some work asynchronously (calling BeginInvoke()) and using a ThreadPool thread as shown below
public void asynchronousWork(object num) { //asynchronous work to be done Console.WriteLine(num); } public void test() { Action<object> myCustomDelegate = this.asynchronousWork; int x = 7; //Using Delegate myCustomDelegate.BeginInvoke(7, null, null); //Using Threadpool ThreadPool.QueueUserWorkItem(new WaitCallback(asynchronousWork), 7); Thread.Sleep(2000); }
Edit:
BeginInvoke makes sure that a thread from the thread pool is used to execute the asynchronous code , so is there any difference?
Invoke : Executes on the UI thread, but calling thread waits for completion before continuing. Control. BeginInvoke : Executes on the UI thread, and calling thread doesn't wait for completion.
Thread pools do not make sense when you need thread which perform entirely dissimilar and unrelated actions, which cannot be considered "jobs"; e.g., One thread for GUI event handling, another for backend processing. Thread pools also don't make sense when processing forms a pipeline.
Delegates allow methods to be passed as parameters. Delegates can be used to define callback methods. Delegates can be chained together; for example, multiple methods can be called on a single event. Methods don't have to match the delegate type exactly.
BeginInvoke(Action) Executes the specified delegate asynchronously on the thread that the control's underlying handle was created on. BeginInvoke(Delegate) Executes the specified delegate asynchronously on the thread that the control's underlying handle was created on.
Joe Duffy, in his Concurrent Programming on Windows
book (page 418), says this about Delegate.BeginInvoke
:
All delegate types, by convention offer a BeginInvoke and
EndInvoke
method alongside the ordinary synchronousInvoke
method. While this is a nice programming model feature, you should stay away from them wherever possible. The implementation uses remoting infrastructure which imposes a sizable overhead to asynchronous invocation. Queue work to the thread pool directly is often a better approach, though that means you have to co-ordinate the rendezvous logic yourself.
EDIT: I created the following simple test of the relative overheads:
int counter = 0; int iterations = 1000000; Action d = () => { Interlocked.Increment(ref counter); }; var stopwatch = new System.Diagnostics.Stopwatch(); stopwatch.Start(); for (int i = 0; i < iterations; i++) { var asyncResult = d.BeginInvoke(null, null); } do { } while(counter < iterations); stopwatch.Stop(); Console.WriteLine("Took {0}ms", stopwatch.ElapsedMilliseconds); Console.ReadLine();
On my machine the above test runs in around 20 seconds. Replacing the BeginInvoke
call with
System.Threading.ThreadPool.QueueUserWorkItem(state => { Interlocked.Increment(ref counter); });
changes the running time to 864ms.
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