views:

314

answers:

6

Hi all,

I have a method which I would like to invoke asynchronously:

void Foo()
{
}

I can indeed invoke this asynchronously by the following:

delegate void DVoidMethod();
DVoidMethod FooDelegate = new DVoidMethod(Foo);
FooDelegate.BeginInvoke(null,null);

Has anyone got any alternatives?

I think three lines of code is too much?

+8  A: 

Disclaimer:

Don't use this in real code. This is just an attempt to shorten the code OP mentioned. To do real async calls without getting results back, use:

ThreadPool.QueueUserWorkItem(stateObject => Foo());


Use Action and Func delegates in the framework:

new Action(Foo).BeginInvoke(null, null);

Action<T> has been around since 2.0. Other variants are added in 3.5. On 2.0, you can, however, declare a bunch of them somewhere manually for further use; or even better, use LINQBridge.

Mehrdad Afshari
+1 (Note: requires framework 3.5)
Simon P Stevens
@Simon, the Action delegate doesn't require the 3.5 Framework
Andreas Grech
Microsoft itself (Joe Duffy) has advised against the .BeginInvoke as it goes through entire remoting stack. I'd rather schedule to the ThreadPool (or make it a Task, in 4.0)
zvolkov
zvolkov: I just shortened the OP's code.
Mehrdad Afshari
@Simon: Actually, I noticed that this specific version requires 3.5, as the `Foo` that the OP defines is parameterless. `Action` without parameters is also added in 3.5.
Mehrdad Afshari
@Dreas: Doesn't it? Frick..Sorry...my bad...(You're right, it was introduced in 2.0: http://msdn.microsoft.com/en-us/library/018hxwa8(VS.80).aspx)
Simon P Stevens
You still need to call EndInvoke for this. http://www.interact-sw.co.uk/iangblog/2005/05/16/endinvokerequired Simon P Stevens has the correct answer using the ThreadPool
Wilka
Any time you call BeginInvoke, you have to call EndInvoke or you leak memory (possibly) and a WaitHandle (definitely), which get cached waiting for EndInvoke. -1.
Will
Hey guys, I **agree** that you shouldn't do that. The question is **tagged code-golf** and this is just an attempt to shorten the code size.
Mehrdad Afshari
Nice. If I could I'd give you another +1 for your edit. That lambda inside the QueueUserWorkItem is a cool way round the fact that WaitCallback requires an Object param. It's always bugged me that any method I want to call from QueueUserWorkItem has to take a state object that I'm not even using.
Simon P Stevens
@Simon: The idea of this trick has been around since 2.0 days: `delegate { Foo(); }`.
Mehrdad Afshari
+3  A: 

You can knock it down to two lines (in .Net 1.1 and earlier) with simply:

delegate void DVoidMethod();
new FooDelegate(DVoidMethod).BeginInvoke(null, null)

But in the 2.0 and later versions.. the syntax from Mehrdad works.

Refer to the Action delegate for 2.0 and later at MSDN at:

http://msdn.microsoft.com/en-us/library/018hxwa8(VS.80).aspx

Jeff Fritz
Thanks for the 2.0 answer
divinci
edit: the answer for 1.1!
divinci
+6  A: 

How about:

ThreadPool.QueueUserWorkItem(new WaitCallback(Foo));
Simon P Stevens
While this is the technically better method to accomplish that, you can't just get a WaitCallback directly from a method. The WaitCallback signature requires an `object` parameter.
Mehrdad Afshari
+2  A: 

Without using Action and Func you could use the MethodInvoker in the case of the void () delegate:

new MethodInvoker(Foo).BeginInvoke(null, null);

Also, it should be noted that if you use the BeginInvoke method you have to call EndInvoke when the delegate has completed execution.. so this line above will have to change to either use a callback or you need to keep a reference to the delegate.. Like so:

MethodInvoker mi = null;
IAsyncResult ar = null;

ar = (mi = new MethodInvoker(Foo)).BeginInvoke(null,null);


.. sometime later after the delegate has completed executing
mi.EndInvoke(ar);

This is true whenever you use BeginInvoke. So I guess in the end I wouldn't recommend using the BeginInvoke method..

@Steven's solution using the ThreadPool is a much better solution in my opinion.. and his oviously:)

Miky Dinescu
+1 for EndInvoke. See http://msdn.microsoft.com/en-us/library/2e08f6yc.aspx: "No matter which technique you use, always call EndInvoke to complete your asynchronous call. "
John Saunders
+1 for good link John :)
divinci
+1  A: 

Strictly speaking I wouldn't worry about the number of lines of code something takes from a performance perspective because you have no idea how much actual code is behind the functions you're calling.

+1 for valid point
divinci
A: 

Old thread, but I couldn't resist piling on.

You indeed must call EndInvoke to avoid leaks, even if you're not using the result or reacting to the method's completion. But that doesn't mean it has to be ugly.

BeginInvoke expects an AsyncCallback as the callback parameter. An AsyncCallback's signature is a void that takes an IAsyncResult. EndInvoke has that signature, so:

    //waste some time...
    void Foo() {}
    void InvokeFoo()
    {
        Action fooer = () => Foo();
        fooer.BeginInvoke(fooer.EndInvoke, null);            
    }
    void InvokeFoo2()
    {
        // or, less concise but some consider more readable:
        Action fooer = new Action(Foo); //...invoke doesn't change
    }
Paul Smith