在BeginInvoke
之后进行回调,AsyncResult.AsyncDelegate
需要转换为正确的类型,然后才能访问EndInvoke
。
但是我使用泛型,所以我需要为N个通用方法定义N个回调吗?
这是班级:
public class Async
{
public delegate object Func(); //void with no parameter
public delegate TResult Func<T, TResult>(T arg); //one parameter with result
public static void Execute(IAsyncSubscriber subscriber, Func action)
{
action.BeginInvoke(Callback, subscriber);
}
public static void Execute<T, T1>(IAsyncSubscriber subscriber, T param, Func<T, T1> action)
{
action.BeginInvoke(param, Callback, subscriber);
}
private static void Callback(IAsyncResult ar)
{
AsyncResult result = (AsyncResult)ar;
IAsyncSubscriber subscriber = (IAsyncSubscriber)result.AsyncState;
Func action = (Func) result.AsyncDelegate;
object returnValue = action.EndInvoke(result); //To call endinvoke
subscriber.Callback(returnValue);
}
}
答案 0 :(得分:4)
有几种方法可以避免定义N个回调:
您可以在BeginInvoke调用中将相应的EndInvoke方法作为状态传递。 e.g。
private delegate T EndInvokeDelegate<T>(IAsyncResult ar);
public static void Execute<T, T1>(IAsyncSubscriber subscriber, T param, Func<T, T1> action)
{
action.BeginInvoke(param, Callback<T1>, new object[]{subscriber, new new EndInvokeDelegate<T1>(action.EndInvoke)});
}
public static void Execute<T, T1, T2>(IAsyncSubscriber subscriber, T param1, T1 param2, Func<T, T1, T2> action)
{
action.BeginInvoke(param1, param2, Callback<T2>, new object[]{subscriber, new new EndInvokeDelegate<T2>(action.EndInvoke)});
}
private static void Callback<TR>(IAsyncResult ar)
{
object[] stateArr = (object[])ar.AsyncState;
IAsyncSubscriber subscriber = (IAsyncSubscriber)stateArr[0];
EndInvokeDelegate<TR> action = (EndInvokeDelegate<TR>)stateArray[1];
TR returnValue = action(ar);
subscriber.Callback(returnValue);
}
你也可以通过将stateArray [1]视为MultiCastDelegate并在其上使用DynamicInvoke来使回调非泛型,但这会很慢。
对于.Net 2.0和3.0,您可以使用反射,例如
Type actionType= result.AsyncDelegate.GetType();
var minfo = actionType.GetMethod("EndInvoke");
object returnValue = minfo.Invoke(res.AsyncDelegate, new object[] { ar });
对于.Net 4.0,您可以使用动态。 e.g。
dynamic action = result.AsyncDelegate;
object returnValue = action.EndInvoke(result);
答案 1 :(得分:1)
如果我理解正确,你的假设是正确的。您需要定义N
回调。
从好的方面来说,你只会这样做一次,所以没有大事,只需要一点点重复工作:)