What's the difference between QueueUserWorkItem() and BeginInvoke(), for performing an asynchronous activity with no return types needed
The main thing I can think of with QueueUserWorkItem
is that you have to use the WaitCallback
delegate type, which looks tricky if you already have a SomeRandomDelegate
instance and some args. The good news is that you can fix this with a closure:
ThreadPool.QueueUserWorkItem( delegate { someDelegate(arg1, arg2); });
This pattern also ensures you get proper strong typing at compile time (unlike passing an object
state arg to QueueUserWorkItem
and casting it in the target method). This pattern can also be used when calling methods directly:
ThreadPool.QueueUserWorkItem( delegate { SomeMethod(arg1, arg2); });
Obviously, without an EndInvoke
equivalent, you also can't get a return value back out unless you call a method / raise an event / etc at the end of your method... on a related note, you need to be careful with exception handling.
http://blogs.msdn.com/cbrumme/archive/2003/07/14/51495.aspx
says:
"One surprising fact is that this is also why Delegate.BeginInvoke / EndInvoke are so slow compared to equivalent techniques like ThreadPool.QueueUserWorkItem (or UnsafeQueueUserWorkItem if you understand the security implications and want to be really efficient). The codepath for BeginInvoke / EndInvoke quickly turns into the common Message processing code of the general remoting pathway."
The EndInvoke() has a useful but rarely mentioned behavior - it rethrows all unhandled exceptions that the delegate generated in the context of the original thread so you can move the exception processing logic into the main code.
Also, if your delegate has out/ref parameters, they will be added to the EndInvoke() signature allowing you to get them when method finishes execution.