Is Endinvoke() Optional, Sort-Of Optional, or Definitely Not Optional

Is EndInvoke() optional, sort-of optional, or definitely not optional?

Delegate.EndInvoke is documented as a thou shalt call this (i.e. necessary - else leaks happen) - from msdn:

Important Note

No matter which technique you use,
always call EndInvoke to complete your
asynchronous call.

Control.EndInvoke is OK to ignore for fire-and-forget methods - from msdn:

You can call EndInvoke to retrieve the
return value from the delegate, if
neccesary, but this is not required.

However - if you are using Delegate.BeginInvoke and don't want the result, consider using ThreadPool.QueueUserWorkItem instead - it'll make life a lot easier, and avoid the pain of IAsyncResult etc.

EndInvoke() - optional or not?

For Delegate.EndInvoke, you should call it. For Control.EndInvoke, the WinForms team has said that you don't need to call it. I don't know about the equivalent for WPF, but I think it's a good idea to do so unless you've got a really good reason to believe you don't have to.

I have some "fire and forget" code for delegates in my threading article - about half way down (search for "fire").

Asynchronous Invoking - Is EndInvoke required?

You can call EndInvoke to retrieve the return value from the delegate, if neccesary, but this is not required. EndInvoke will block until the return value can be retrieved.

Source:http://msdn.microsoft.com/en-us/library/0b1bf3y3.aspx under Remarks

What exactly does Delegate.EndInvoke do? Is it necessary to call?

The main practical concerns are deterministically cleaning up a wait handle resource (if you chose to create the handle by referencing it) and making sure that Exceptions are propagated properly.

That said, what I would recommend is to move away from the slightly schizophrenic asynchronous pattern in the earlier .NET framework and use TPL, which has a much cleaner continuation model. The TPL even has some nice wrapping functionality to help deal with the older Begin/End style of calling:

http://msdn.microsoft.com/en-us/library/dd997423.aspx

Why does BackgroundWorker not need to call EndInvoke when it calls BeginInvoke on a delegate?

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.

Must every BeginInvoke be followed by an EndInvoke?

Unless the documentation for an interface explicitly says otherwise you must call EndInvoke for every place you call BeginInvoke. The primary reason is that EndInvoke is the only time where the owner can safely free certain resources that may be allocated for the BeginInvoke call (such as a WaitHandle).

But there are exceptions to this rule. APIs such as Control.BeginInvoke do not require an EndInvoke but it's explicit in the documentation.

What happens if an asynchronous delegate call never returns?

I think this post talks about it very well:

From the post:

You can't terminate an executing async delegate if it's not your thread, but you can if it is. If you use the common BeginInvoke type methods, you get a thread pool thread managed by the framework. If you use the Thread() class you get you own thread to manage, start, suspend, etc. as you like.

Developing asychronously requires that one decide who will manage the threads. The many different methods that execute asynchronously are using the ThreadPool threads behind the scenes.

Since you can't/shouldn't terminate a thread pool thread then you must design you code to communicate with the thread so that it can exit. The MSDN examples for the BackgroundWorker component demonstrates this kind of communication.

Sometimes your code may have the thread blocking waiting for IO. Here you would normally use a multiple object wait instead, waiting for IO or for a ManualResetEvent.

So in short, youll need to find a way to manage the threads yourself if there is a possibility of timing out and you want the thread to end.

Is this a proper way of calling synchronous methods asynchronously?

The way you did it is fine, another way to do this that works on .NET 3.5 is using the ThreadPool class instead

ThreadPool.QueueUserWorkItem(new WaitCallback((a) => handler.Invoke(sender, e)))

Also if handler happens to be a derived from control, you are allowed to call BeginInvoke without a corresponding EndInvoke.

Should I create my AsyncCallback as a new object and is EndInvoke optional?

 new AsyncCallback(ExportDatabaseCallback)

is just the old, longer way to create a delegate. Your code does exactly the same.

And EndInvoke() is sometimes optional but you don't want to know when and when not. Just call it, and you're always right.



Related Topics



Leave a reply



Submit