4

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);
        }
    }
4

2 に答える 2

4

N個のコールバックの定義を回避する方法はいくつかあります。

  1. 対応するEndInvokeメソッドをBeginInvoke呼び出しの状態として渡すことができます。例えば

    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を使用することで、コールバックを非ジェネリックにすることもできますが、これは遅くなります。

  2. .Net 2.0および3.0の場合、リフレクションを使用できます。

    Type actionType= result.AsyncDelegate.GetType();
    var minfo = actionType.GetMethod("EndInvoke");
    object returnValue = minfo.Invoke(res.AsyncDelegate, new object[] { ar });
    
  3. .Net 4.0では、動的を使用できます。例えば

    dynamic action = result.AsyncDelegate; 
    object returnValue = action.EndInvoke(result);
    
于 2012-07-10T11:24:42.210 に答える
1

私が正しく理解していれば、あなたの仮定は正しいです。コールバックを定義する必要がありNます。

明るい面では、これは1回だけ行うので、大したことはなく、少し繰り返し作業するだけです:)

于 2012-07-09T10:43:38.933 に答える