2010-03-12 98 views
5

我有一个ContextMenuStrip控件,允许您执行一个动作是两种不同的风格:SyncAsync动作T同步和异步

我试图掩盖使用泛型所以我做了这一切:

public class BaseContextMenu<T> : IContextMenu 
{ 
    private T executor; 

    public void Exec(Action<T> action) 
    { 
     action.Invoke(this.executor); 
    } 

    public void ExecAsync(Action<T> asyncAction) 
    { 
     // ... 
    } 

我怎么可以为了执行通用的动作和“有所作为”,在此期间的菜单写异步方法? 我看到的BeginInvoke的签名是这样的:

asyncAction.BeginInvoke(this.executor, IAsyncCallback, object); 

回答

8

这里是杰弗里里希特对.NET异步编程模型的文章。 http://msdn.microsoft.com/en-us/magazine/cc163467.aspx

这里是BeginInvoke的如何使用的例子:

public class BaseContextMenu<T> : IContextMenu 
{ 
    private T executor; 

    public void Exec(Action<T> action) 
    { 
     action.Invoke(this.executor); 
    } 

    public void ExecAsync(Action<T> asyncAction, AsyncCallback callback) 
    { 
     asyncAction.BeginInvoke(this.executor, callback, asyncAction); 
    } 
} 

这里是一个回调方法,可以传递给ExecAsync:

private void Callback(IAsyncResult asyncResult) 
{ 
    Action<T> asyncAction = (Action<T>) asyncResult.AsyncState; 
    asyncAction.EndInvoke(asyncResult); 
} 
+0

让我看看 – Raffaeu 2010-03-12 16:57:08

+0

谢谢,这就是我一直在寻找的东西。我只是遇到了lambda表达式的一个问题,我不需要关于多线程编程的课程。 ;-) – Raffaeu 2010-03-12 17:23:47

+0

+1。杰夫的文章。这真的很有见地,帮了我很多。 – IAbstract 2010-12-31 15:21:16

2

简单的选择:

// need this for the AsyncResult class below 
using System.Runtime.Remoting.Messaging; 

public class BaseContextMenu<T> : IContextMenu 
{ 
    private T executor; 

    public void Exec(Action<T> action) { 
     action.Invoke(this.executor); 
    } 

    public void ExecAsync(Action<T> asyncAction) { 
     // specify what method to call when asyncAction completes 
     asyncAction.BeginInvoke(this.executor, ExecAsyncCallback, null); 
    } 

    // this method gets called at the end of the asynchronous action 
    private void ExecAsyncCallback(IAsyncResult result) { 
     var asyncResult = result as AsyncResult; 
     if (asyncResult != null) { 
      var d = asyncResult.AsyncDelegate as Action<T>; 
      if (d != null) 
       // all calls to BeginInvoke must be matched with calls to 
       // EndInvoke according to the MSDN documentation 
       d.EndInvoke(result); 
     } 
    } 
}