2011-08-23 224 views
2

我有一个使用的BeginXXX EndXxx异步模式库(显然,下面的代码是简化):异步函数进行异步调用

ILibrary 
{ 
    IAsyncResult BeginAction(string name, AsyncCallback callback, object state); 
    int EndAction(IAsyncResult asyncResult, out object state) 
} 

我试图建立一个使用该库类,和实现了相同的模式本身:

Manager 
{ 
    private ILibrary library; 

    public IAsyncResult BeginMultipleActions(IEnumerable<string> names, 
              AsyncCallback callback, object state) 
    { 
     var handles = new List<IAsyncResult>(); 
     foreach(string name in names) 
     { 
      var handle = library.BeginAction(name, OnSingleActionCompleted, null); 
      handles.Add(handle); 
     } 
     //??? 
    } 
    public int EndMultipleActions(IAsyncResult asyncResult, out object state) 
    { 
     //??? 
    } 

    private void OnSingleActionCompleted(IAsyncResult asyncResult) 
    { 
     //??? 
    } 
} 

我已经试过了几个解决方案(使用ManualResetEvent的),但我发现我的代码非常难看。什么是最干净的方法(在C#3.5中)而不会丢失功能(回调,等待句柄,...)?

+1

如果你可以使用.NET 4,你可以使用带ContinueWith和Wait *方法的TPL – oleksii

+0

不幸的是,我被3.5和I不能使用Reactive Extensions – Luk

回答

1

为了能够成功地实现你所描述的模式,你应该能够调用传递到您的BeginMultipleActions方法的所有单个动作完成后回调。使用事件并等待它们,可能会挫败你做异步调用的唯一目的,因为它们会阻塞这些线程。您传递给单个操作的回调应能够确定何时完成所有方法,然后将客户端提供的回调调用到BeginMultipleActions方法。这里有一个可能为你做的样本(我没有测试过)。但是,这只是为了让你开始,并不完美。将有几个细微差别,你将不得不通过。

interface ILibrary 
{ 
    IAsyncResult BeginAction(string name, AsyncCallback callback, object state); 
    int EndAction(IAsyncResult asyncResult, out object state); 
} 

class Manager 
{ 
    private ILibrary library; 

    class AsyncCallInfo : IAsyncResult 
    { 
     public int PendingOps; 
     public AsyncCallback Callback { get; set; } 
     public object AsyncState { get; set; } 

     public WaitHandle AsyncWaitHandle 
     { 
      // Implement this if needed 
      get { throw new NotImplementedException(); } 
     } 

     public bool CompletedSynchronously 
     { 
      get { return false; } 
     } 

     public bool IsCompleted 
     { 
      get { return PendingOps == 0; } 
     } 
    } 

    public IAsyncResult BeginMultipleActions(IEnumerable<string> names, 
              AsyncCallback callback, object state) 
    { 
     var callInfo = new AsyncCallInfo { 
      Callback = callback, 
      AsyncState = state 
     }; 

     callInfo.PendingOps = names.Count(); 
     foreach (string name in names) 
     { 
      library.BeginAction(name, ar => OnSingleActionCompleted(ar, callInfo), null); 
     } 

     return callInfo; 
    } 

    public int EndMultipleActions(IAsyncResult asyncResult, out object state) 
    { 
     // do your stuff 
     state = asyncResult.AsyncState; 
     return 0; 
    } 

    private void OnSingleActionCompleted(IAsyncResult asyncResult, AsyncCallInfo callInfo) 
    { 
     //??? 
     Interlocked.Decrement(ref callInfo.PendingOps); 
     if (callInfo.PendingOps == 0) 
     { 
      callInfo.Callback(callInfo); 
     } 
    } 
} 

我建议你看看Jeffrey Richter的AsyncEnumerator。它简化了编写异步代码的模式并支持几种异步实现模式 - http://msdn.microsoft.com/en-us/magazine/cc546608.aspx

+0

这与我所做的大致相同,非常感谢您验证我的预感! – Luk