views:

160

answers:

3

I am trying to create an extension method for the generic delegate Action<T> to be able to make simple asynchronous calls on Action<T> methods. It basically just implements the pattern for when you want to execute the method and don't care about it's progress:

public static class ActionExtensions
{
    public static void AsyncInvoke<T>(this Action<T> action, T param) {
        action.BeginInvoke(param, AsyncActionCallback, action);
    }

    private static void AsyncActionCallback<T>(IAsyncResult asyncResult) {
        Action<T> action = (Action<T>)asyncResult.AsyncState;
        action.EndInvoke(asyncResult);
    }
}

The problem is that it won't compile because of the extra <T> that makes the AsyncActionCallback generic and have a different signature than expected. The signature void AsyncActionCallback(IAsyncResult) is expected.

Does anyone know how to work around this or to accomlish what I am trying to do?

A: 

AsyncActionCallback<T> ?

Disclaimer: not sure about the above, could be one of those 'limitations'.

leppie
I am not sure what you mean. I am using that exact same signature in the code I posted. But again that would not compile because the compiler does not expect the type parameter <T>. Anyway, Darin's solution using a lamda instead of the delegate works.
Hermann
+6  A: 
public static void AsyncInvoke<T>(this Action<T> action, T param)
{
    action.BeginInvoke(param, asyncResult => 
    {
        Action<T> a = (Action<T>)asyncResult.AsyncState;
        a.EndInvoke(asyncResult);
    }, action);
}
Darin Dimitrov
That's one way :) Good thinking.
leppie
Awesome, thanks so much for that blazing fast answer! It's interesting how lambdas enable something that was not possible before. I guess it's not just sugar after all!
Hermann
Note that this approach may let any errors that occur during invocation get dropped on the floor. You might want to wrap the contents of the lambda inside a try { } catch { }.
Kevin Gadd
A: 

If you want to keep your function separated (not as lambda) what about something like this:

public static void AsyncInvoke<T>(Action<T> action, T param)
{
    action.BeginInvoke(param, new AsyncCallback(AsyncActionCallback<T>), action);
}
Rene