Reputation: 189
This post says that when you call the BeginInvoke
method on a delegate, it is always necessary to call the EndInvoke
method. Another post backs it up and suggests the class BackgroundWorker
as an alternative.
I used ILSpy to decompile BackgroundWorker
and I have found out that actually, EndInvoke
is never called in this class, even though it does use BeginInvoke
on a delegate.
Does this mean that BackgroundWorkder
is ill-implemented, or is calling EndInvoke
not so necessary after all?
(The issue with exceptions being lost is irrelevant, since the whole method being invoked is enclosed in a try-catch block)
On a similar matter: it there a clear reason why BeginInvoke
was chosen in implementation of BackgroundWorker
over say, ThreadPool.QueueUserWorkItem()
?
Edit: the source code of BackgroundWorker
can be viewed here.
Upvotes: 3
Views: 165
Reputation: 941505
I looked for the man-behind-the-curtain for a while. The CLR has secret knowledge of the SynchronizationContext class so technically it could be involved here. Found absolutely nothing.
Until I checked what I should have done in the first place, actually verify the claim that EndInvoke() is required:
using System;
class Program {
static void Main(string[] args) {
Action d = null;
d = new Action(() => {
d.BeginInvoke(null, null);
});
d();
Console.ReadLine();
}
}
Runs like gangbusters and consumes plenty of handles. But it won't blow up, they never go over ~2000 and memory usage is completely stable.
So perhaps it is appropriate to tweak the claim that calling a delegate's EndInvoke() is required. If you have a priori knowledge that the delegate target will not doing anything unusual, like calling into another AppDomain, running native code or activate remoted code then you can get away with not calling EndInvoke(). A guarantee that BackgroundWorker can provide. I can never make that claim stick as just a mere SO user. But Microsoft does it so it must be okay. A comment in the source code would have been nice.
Upvotes: 1