I need to make a retraction.  It's just come to my attention that the
runtime guys are reserving the right to leak stuff if you never call
EndInvoke.  In the course of trying to pin down who was saying what on
this topic, I ran across this statement in the .net sdk docs for the 1.1
framework:

"CAUTION   Always call EndInvoke after your asynchronous call
completes."

As far as I can tell, this is the first time they've come right out and
said this.  And it's contrary to what guys like Box and Grimes have
published in books and articles on this topic [2,3].

So if you want fire-and-forget semantics, you'll have to roll it
yourself.  An example of one possible approach appears below my sig as
note [4].

Apparantly this is still being discussed internally, so there's a chance
they might retract the cautionary note they've introduced in the 1.1
docs; but that's probably unlikely at this point.

-Mike
DevelopMentor
http://staff.develop.com/woodring

[1]
ms-help://MS.NETFrameworkSDKv1.1/cpguidenf/html/cpovrasynchronousprogram
mingoverview.htm
[2] "Essential .NET", 1st Ed., by Don Box, page 194.
[3] ms-help://MS.MSDNQTR.2003JAN.1033/dnmag01/html/ASync0108.htm
[4]

// AsyncHelper
//
// This class provides a FireAndForget method that facilitates
// calling an arbitrary method asynchronously w/o worrying about
// or waiting for the return value.
//
// The usage model is along these lines (example assumes
// the existence of void SomeMethod(string, double).
//
// SomeDelegate sd = new SomeDelegate(SomeMethod);
// AsyncHelper.FireAndForget(sd, "pi", 3.1415927);
//
// Note - there's an extra (IMO) level of indirection in the
// following code that I don't think should be necessary.  The
// goal is to call Delegate.DynamicInvoke using BeginInvoke.
// Using BeginInvoke gets us asynchrony, using DynamicInvoke
// makes this generically reusable for any delegate.  However,
// when I call DynamicInvoke directly I get an undetailed
// execution engine fatal error.  When I use BeginInvoke to
// call a shim method that just turns around and calls
// DynamicInvoke, things work.  Strange (and consistent on
// the 1.0 and 1.1 runtimes).
//
public class AsyncHelper
{
    delegate void DynamicInvokeShimProc( Delegate d, object[] args );

    static DynamicInvokeShimProc dynamicInvokeShim = new
DynamicInvokeShimProc(DynamicInvokeShim);
    static AsyncCallback dynamicInvokeDone = new
AsyncCallback(DynamicInvokeDone);

    public static void FireAndForget( Delegate d, params object[] args )
    {
        dynamicInvokeShim.BeginInvoke(d, args, dynamicInvokeDone, null);
    }

    static void DynamicInvokeShim( Delegate d, object[] args )
    {
        d.DynamicInvoke(args);
    }

    static void DynamicInvokeDone( IAsyncResult ar )
    {
        dynamicInvokeShim.EndInvoke(ar);
    }
}


> -----Original Message-----
> From: Moderated discussion of advanced .NET topics.
> [mailto:[EMAIL PROTECTED]] On Behalf Of
> Mike Woodring (DevelopMentor)
> Sent: Monday, January 20, 2003 9:06 PM
> To: [EMAIL PROTECTED]
> Subject: Re: [ADVANCED-DOTNET] Bad mojo to not call
> Delegate.EndInvoke() ?
>
>
> Calling EndInvoke is optional, just as paying attention to the return
> value of a method is optional.  If the function you call returns
> something (or a reference to something), you're free to ignore it (and
> let the garbage collector do it's thing later if the method
> is returning
> a reference to an object).  Same holds true for delegates.  You only
> need to call EndInvoke if you're interested in harvesting the
> outcome of
> the method that was called (i.e., it's return value, any out/ref args,
> or any exception that might be thrown).  If you don't care about the
> outcome, don't call EndInvoke.
>
> This is true whether or not the method you're calling has a
> void/non-void return value.
>
> -Mike
> http://staff.develop.com/woodring
> http://www.develop.com/devresources
>

Reply via email to