将委托类型转换为Delegate并调用EndInvoke

时间:2011-03-13 10:17:32

标签: c# multithreading delegates

我继承了一些我试图重构的冗长,重复的代码。其骨架如下:

private void startThreads() 
{ 
    RunRemoteCmdDelegate runRemoteCmdDlg = new RunRemoteCmdDelegate(services.runRemoteCommand); 

    List<IAsyncResult> returnTags = new List<IAsyncResult>(); 

    // asynchronously invokes the delegate multiple times
    foreach (...) 
    { 
        returnTags.Add(runRemoteCmdDlg.BeginInvoke(...)); 
    } 

    MonitorTasks(runRemoteCmdDlg, messages, returnTags, invokationCounter); 

} 

private void MonitorTasks(RunRemoteCmdDelegate theDelegate, List<IAsyncResult> returnTags) 
{ 

        foreach (IAsyncResult returnTag in returnTags) {
            MessageType message = runRemoteCmdDlg.EndInvoke(returnTag);
            messages.Add(message)
        } 
}

有许多类包含相同的代码,但所有类都具有不同的委托类型。

我想将MonitorTasks方法“拉”到基类中,但它需要使用所有不同类型的委托,例如:

private void MonitorTasks(Delegate theDelegate, List<IAsyncResult> returnTags) 
{ 

        foreach (IAsyncResult returnTag in returnTags) {
            MessageType message = runRemoteCmdDlg.EndInvoke(returnTag);  // DOESN'T COMPILE
            messages.Add(message)
        } 
}

我无法在基本Delegate(或MulticastDelegate)类型上调用EndInvoke(),那么如何编写此方法?我是否需要以不同的方式解决这个问题?

我正在使用C#3.5,那么有没有办法使用Func,Action等,仍然可以调用EndInvoke?

1 个答案:

答案 0 :(得分:1)

您可以使用反射来访问委托的EndInvoke()方法:

using System.Reflection;

private void MonitorTasks(Delegate theDelegate, List<IAsyncResult> returnTags) 
{ 
    MethodInfo endInvoke = theDelegate.GetType().GetMethod("EndInvoke",
        new Type[] { typeof(IAsyncResult) });
    foreach (IAsyncResult returnTag in returnTags) {
        MessageType message = (MessageType) endInvoke.Invoke(theDelegate,
            new object[] { returnTag });
        messages.Add(message);
    } 
}

请参阅this blog,了解更为一般性,即发即弃的问题。