简体   繁体   中英

cast delegate type to Delegate and call EndInvoke

I have inherited some verbose, repetitious code that I am trying to refactor. The bare bones of which are as follows:

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

There are many classes containing this same code but all with different delegate types.

I'd like to 'pull up' the MonitorTasks method into a base class, but it will need to work with all the different types of delegate, for example:

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

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

I can't call EndInvoke() on the base Delegate (or MulticastDelegate) type, so how can I code this method? Do I need to approach this in a different way?

I'm using C#3.5, so is there some way to use Func, Action, etc, and still be able to call EndInvoke?

You can use reflection to access the EndInvoke() method of the delegate:

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

See this blog for a more general, fire-and-forget take on the problem.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM