我有一个使用 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 中)最简洁的方法是什么?
最佳答案
为了能够成功实现您所描述的模式,您应该能够在所有单个操作完成后调用传递到您的 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
关于c# - 异步函数进行异步调用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7159842/