BeginInvoke and resource leaks  
Author Message
Alex Farber





PostPosted: Visual C# General, BeginInvoke and resource leaks Top

From Jeffrey Richter's "CLR via C#":

"You must call Endxxx or you will leak resources. CLR allocates some internal resources when you initiate asynchronous operation. If Endxxx is never called, these resources will be reclaimed only when the process terminates."

This is written about functions like BeginRead and EndRead. Is this correct also for delegates For example:

public delegate void SomeDelegate;
...
SomeDelegate someDelegate;
...
someDelegate += subscription;
...
someDelegate->BeginInvoke();

If I never call someDelegate->EndInvoke, does this create resource leak, as written in the book
According to Richter, the only Beginxxx function which doesn't require Endxxx is Control.BeginInvoke. I can use Control.BeginInvoke instead of someDelegate->BeginInvoke, if my current code has resource leaks. But before changing my code, I want to be sure that this is necessary.



Visual C#4  
 
 
TaylorMichaelL





PostPosted: Visual C# General, BeginInvoke and resource leaks Top

It could. You should always call EndInvoke if you call BeginInvoke. Normally when you async a call the runtime must track some information about the call and its end results. The runtime must know when it no longer needs to keep the information. That is what EndInvoke does. It tells the runtime that the information is no longer needed. What information is stored and for how long is an implementation detail. Best not to risk it.

Michael Taylor - 12/11/06


 
 
Peter Ritchie





PostPosted: Visual C# General, BeginInvoke and resource leaks Top

The only resources that I've been able to track down for compiler-generated delegates (which is what happens when you use the "delegate" keyword) are the wait handles in the AsyncResult class.  EndInvoke does nothing to release those though, the GC would handle that when the AsyncResult no longer had any references to it.

In the case of other classes that have BeginXXX methods, they often use unmanaged resources (like a duplicated handle) for which information is retrieved in the EndXXX.  Those handles need to stay around in order for the appropriate values to retrieved from them.  The retrieval and disposal of those handles is handled by a call to EndXXX.  Ideally, though, the finalizer should also ensure those handles are  freed.  But, it's up to the GC to nondeterministically call the finalizer.  EndXXX would deterministically free the resources which would otherwise be "leaked" until the finalizer is called (assumes a certain level of "perfection" to the implementation of those classes).

The compiler generated delegate methods BeginInvoke and EndInvoke (Invoke is also compiler generated) don't directly allocate any resources--as far as I've been able to tell (and I make no guarantees express or implied)--that would deterministically be freed by a call to EndInvoke.  For example, the process' handle count (from System.Diagnostics.Process.GetCurrentProcess().HandleCount) neither changes when the compiler-generated EndInvoke is called nor when the compiler-generated BeginInvoke is called.

It certainly wouldn't hurt to ensure a delegate's EndInvoke is called and should be considered a good practice.

 
 
Alex Farber





PostPosted: Visual C# General, BeginInvoke and resource leaks Top

This is exactly the problem - I need BeginInvoke without EndInvoke. Exactly like PostMessage in Win32. And I need to decide whether to replace all delegate BeginInvoke calls with Control.BeginInvoke.
From the last post I understand that there are no unmanaged resources in compiler-generated delegate code. However, managed resources which are not released until process exits are also problem. I see that there are different opinions about this.
I will wait some time for additional information. Thank you for the answers.
BTW, I wonder why it is always recommended to call EndInvoke. In multithreaded real-time application it is always better to use asynchronous calls. This prevents deadlocks. I think there are only two reasons to make synchronous call: if I pass pointer to unmanaged memory, or I need result of this call immediately. Using EndInvoke effectively converts asynchronous call to synchronous.
I think delegates should contain safe method to invoke them asynchronously without need to call EndInvoke.

 
 
Mike Danes





PostPosted: Visual C# General, BeginInvoke and resource leaks Top

Hmm, if you want something that behaves exactly like PostMessage in Win32 you probably should use Control.BeginInvoke since this is what it is more or less doing, posting messages to the UI thread. Using BeginInvoke on a delegate will result in the "invoked" method being called on another thread than the UI thread.

As for EndInvoke being syncrhonous: it is synchronous only if the async task has not completed. If you supply an AsyncCallback to BeginInvoke and call EndInvoke from the that callback then EndInvoke does not have to wait for anything because the async task has already completed and anyway the callback runs on another thread than the thread that called BeginInvoke.


 
 
TaylorMichaelL





PostPosted: Visual C# General, BeginInvoke and resource leaks Top

I think, Alex, that saying that a multithreaded program will almost always use async is incorrect. Either that or our definitions are different. I don't consider a simple async call to be enough to make a program multithreaded (MT). Nevertheless a deadlock condition can occur whenever two or more threads compete for the same resource. This can occur in MT programs as well as it can in async calls.

Even more important is that async calls are dangerous in real-time applications. You didn't mention whether your app was hard or soft real-time but in general real-time apps mandate deterministic timing behaviors which is simply not guaranteed with async calls. For RT apps that need deterministic execution you must either execute the logic directly or use your own threading. In both cases the actual timing will still vary due to thread scheduling so true hard real-time is not possible in Windows.

You should not use async calls to try to avoid deadlock issues as it is more likely to create them. Instead use async calls only when you don't want to stall the running thread waiting on the response. The UI is the most common thread but there are many other examples. For example if you are hosting a server you might use an async call (rather than a full blown thread) to handle a client request. Personally I would avoid using async calls if you already running on a background thread as you are only slowing things down even more.

As for using Control.BeginInvoke you can only do that if you are within the context of a control. If you are running some arbitrary code in the UI then you should consider using the BackgroundWorker component instead.

Finally note that async calls don't boil down to sync calls because when you make an async call you start it on some secondary thread. Later when the work is complete you get notified that the work is done (through the callback you passed to the method). This notification occurs on an arbitrary thread and allows you to clean up any resources. As far as the main thread is concerned (the one that made the async call) it is a fire and forget mechanism. It does boil down to a partial sync call when you have to communicate back to the UI but this is true irrelevant of how you make the call. The UI is single threaded so all interaction is serialized.

Michael Taylor - 12/12/06


 
 
Alex Farber





PostPosted: Visual C# General, BeginInvoke and resource leaks Top

>> Finally note that async calls don't boil down to sync calls because when you make an async call you start it on some secondary thread. Later when the work is complete you get notified that the work is done (through the callback you passed to the method). This notification occurs on an arbitrary thread and allows you to clean up any resources.

This looks exactly as I need, but how can this be done for delegate


 
 
Peter Ritchie





PostPosted: Visual C# General, BeginInvoke and resource leaks Top

 
This is exactly the problem - I need BeginInvoke without EndInvoke. Exactly like PostMessage in Win32. And I need to decide whether to replace all delegate BeginInvoke calls with Control.BeginInvoke.
From the last post I understand that there are no unmanaged resources in compiler-generated delegate code. However, managed resources which are not released until process exits are also problem. I see that there are different opinions about this.
I will wait some time for additional information. Thank you for the answers.
BTW, I wonder why it is always recommended to call EndInvoke. In multithreaded real-time application it is always better to use asynchronous calls. This prevents deadlocks. I think there are only two reasons to make synchronous call: if I pass pointer to unmanaged memory, or I need result of this call immediately. Using EndInvoke effectively converts asynchronous call to synchronous.
I think delegates should contain safe method to invoke them asynchronously without need to call EndInvoke.
No one but a Microsoftie can offer a definitive answer on this.

But, managed resources are only guaranteed stay alive until the exit of the application if a reference to their object is kept until application exit.  If there are no references to the object (like AsyncResult) GC will collect those managed resources at some appropriate time.  They will be collected, just not deterministically like using EndInvoke.  Even Control.BeginInvoke would have this problem as the AsyncResult object could not possibly be deterministically freed/disposed without a call to EndInvoke.

Using EndInvoke does not make a synchronous call out of an asynchronous one.  Yes, you *can* use the wait handle in the IAsyncResult interface returned by BeginInvoke to block a thread until the asynchronous call completes; but, you don't have to.  The easiest thing is to pass a callback with the BeginInvoke that will instigate the call to EndInvoke without blocking any threads.  This gets a little tricky in that we're dealing with compiler-generated methods; but, with the assumption that you don't need a result from the asynchronous delegate we can create a generalized method for invoking EndInvoke.  First the assumption is that you don't have a return value from your delegate.  In this case your compiler generated EndInvoke will always be "void EndInvoke(IAsyncResult)".  From this we can create a delegate for that EndInvoke Signature:

delegate void EndInvokeDelegate ( IAsyncResult result );

...which can be used for any delegate that returns void.  Next, it's just a matter of creating the callback and getting an EndInvokeDelegate (remember a delegate is an object/method pair so we only need the delegate) into the callback--which can be accomplished by passing it as a parameter to BeginInvoke:

/// <summary>

/// Generalized AsyncCallback method to simply call an EndInvokeDelegate

/// </summary>

/// <param name="asyncResult"></param>

void AsyncCallCompleted ( IAsyncResult asyncResult )

{

    object[] parameters = asyncResult.AsyncState as object[];

    if (parameters != null && parameters.Length > 0)

    {

        EndInvokeDelegate endInvokeDelegate = parameters[0] as EndInvokeDelegate;

        if (endInvokeDelegate != null)

        {

            endInvokeDelegate.Invoke(asyncResult);

        }

    }

}

And, to make an asychronous call to "SomeMethod" via an asychronous delegate:

EventHandler ev = new EventHandler(SomeMethod);

ev.BeginInvoke(this, EventArgs.Empty, new AsyncCallback(AsyncCallCompleted), new object[] { new EndInvokeDelegate(ev.EndInvoke) });

Now, when the call to "SomeMethod" is complete the runtime will call AsyncCallCompleted that will look for an object array as the AsyncState (remembering that the AsyncState is the last parameter passed to BeginInvoke) and if it is an object array and the first element (but, just as easily the last element could be used) in the array is an EndInvokeDelegate it is simply called.

This particular example uses a method (SomeMethod) whose signature is void SomeMethod(object sender, EventArgs e); but you could use anything.  If you provide that detail I can re-write the above code to match that...



 
 
Peter Ritchie





PostPosted: Visual C# General, BeginInvoke and resource leaks Top

BTW, I'm also attempting to get a definitive answer on whether EndInvoke must be called on an asynchronous delegate. It make take some time as we're not only dealing with the CLR but "compiler-generated" code. My previous code should placate any resource leak concerns until a definitive answer is received...

 
 
Alex Farber





PostPosted: Visual C# General, BeginInvoke and resource leaks Top

>> Using EndInvoke does not make a synchronous call out of an asynchronous one.  Yes, you *can* use the wait handle in the IAsyncResult interface returned by BeginInvoke to block a thread until the asynchronous call completes; but, you don't have to.

Shame on me, this is the point I am missing! Only wating for IAsyncResult.AsyncWaitHandle makes the call synchronous, right
So, in my case, it is enough to write:

IAsyncResult result = someDelegate->BeginInvoke();
someDelegate->EndInvoke(result);

and this is still asynchronous call with 100% cleanup


 
 
Peter Ritchie





PostPosted: Visual C# General, BeginInvoke and resource leaks Top

>> Using EndInvoke does not make a synchronous call out of an asynchronous one. Yes, you *can* use the wait handle in the IAsyncResult interface returned by BeginInvoke to block a thread until the asynchronous call completes; but, you don't have to.

Shame on me, this is the point I am missing! Only wating for IAsyncResult.AsyncWaitHandle makes the call synchronous, right
So, in my case, it is enough to write:

IAsyncResult result = someDelegate->BeginInvoke();
someDelegate->EndInvoke(result);

and this is still asynchronous call with 100% cleanup

When you do that your delegate will be running asynchronously, but the call to EndInvoke will block until that delegate has finished executing. This probably isn't what you want as it kind of defeats the purpose of asynchronous code...

 
 
Alex Farber





PostPosted: Visual C# General, BeginInvoke and resource leaks Top

This is exactly the reason I asked this question.
I will try to understand your code, for now I have simple Control.BeginInvoke solution.
Thanks.


 
 
theblueeyz





PostPosted: Visual C# General, BeginInvoke and resource leaks Top

/// <summary>

/// Generalized AsyncCallback method to simply call an EndInvokeDelegate

/// </summary>

/// <param name="asyncResult"></param>

void AsyncCallCompleted ( IAsyncResult asyncResult )

{

object[] parameters = asyncResult.AsyncState as object[];

if (parameters != null && parameters.Length > 0)

{

EndInvokeDelegate endInvokeDelegate = parameters[0] as EndInvokeDelegate;

if (endInvokeDelegate != null)

{

endInvokeDelegate.Invoke(asyncResult);

}

}

}

And, to make an asychronous call to "SomeMethod" via an asychronous delegate:

EventHandler ev = new EventHandler(SomeMethod);

ev.BeginInvoke(this, EventArgs.Empty, new AsyncCallback(AsyncCallCompleted), new object[] { new EndInvokeDelegate(ev.EndInvoke) });

Hi Peter,

Just curious - how is the above quoted piece of code different than the following:

void AsyncCallCompleted ( IAsyncResult asyncResult )

{

object[] parameters = asyncResult.AsyncState as object[];

if (parameters != null && parameters.Length > 0)

{

EndInvokeDelegate endInvokeDelegate = parameters[0] as EndInvokeDelegate;

if (endInvokeDelegate != null)

{

endInvokeDelegate.EndInvoke(asyncResult);

}

}

}

You call Invoke(); I call EndInvoke. I thought calling EndInvoke was the desired behavior. Are these the same



 
 
Alex Farber





PostPosted: Visual C# General, BeginInvoke and resource leaks Top

I think this is correct:

EventHandler ev = new EventHandler(SomeMethod);

ev.BeginInvoke(this, EventArgs.Empty, new AsyncCallback(AsyncCallCompleted), new object[] { new EndInvokeDelegate(ev.EndInvoke) });

...
endInvokeDelegate.Invoke(asyncResult);   // here endInvokeDelegate calls ev.EndInvoke

Really, it takes some time to understand this.


 
 
Peter Ritchie





PostPosted: Visual C# General, BeginInvoke and resource leaks Top

/// <summary>

/// Generalized AsyncCallback method to simply call an EndInvokeDelegate

/// </summary>

/// <param name="asyncResult"></param>

void AsyncCallCompleted ( IAsyncResult asyncResult )

{

object[] parameters = asyncResult.AsyncState as object[];

if (parameters != null && parameters.Length > 0)

{

EndInvokeDelegate endInvokeDelegate = parameters[0] as EndInvokeDelegate;

if (endInvokeDelegate != null)

{

endInvokeDelegate.Invoke(asyncResult);

}

}

}

And, to make an asychronous call to "SomeMethod" via an asychronous delegate:

EventHandler ev = new EventHandler(SomeMethod);

ev.BeginInvoke(this, EventArgs.Empty, new AsyncCallback(AsyncCallCompleted), new object[] { new EndInvokeDelegate(ev.EndInvoke) });

Hi Peter,

Just curious - how is the above quoted piece of code different than the following:

void AsyncCallCompleted ( IAsyncResult asyncResult )

{

object[] parameters = asyncResult.AsyncState as object[];

if (parameters != null && parameters.Length > 0)

{

EndInvokeDelegate endInvokeDelegate = parameters[0] as EndInvokeDelegate;

if (endInvokeDelegate != null)

{

endInvokeDelegate.EndInvoke(asyncResult);

}

}

}

You call Invoke(); I call EndInvoke. I thought calling EndInvoke was the desired behavior. Are these the same

Actually, endInvokeDelegate.Invoke calls the original delegate's EndInvoke and yours calls the delegate's delegate's EndInvoke. The delegate given to AsyncCallCompleted is essentially a pointer to the EndInvoke we want to call. So, we just Invoke that method. "endInvokeDelegate.EndInvoke" would be used if you first called "endInvokeDelegate.BeginInvoke". I know, it's thoroughly confusing.