c# - 异步函数进行异步调用

标签 c# .net multithreading c#-3.0 iasyncresult

我有一个使用 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/

相关文章:

.net - 单击菜单项时验证 DataGridView

multithreading - 在 MVC 4 async ApiController 中使用 Task.Factory.StartNew?

c# - 如何在不实际遍历所有图片像素的情况下使 C# 中的图片变亮?

c# - 将所有子域添加到 CORS azure 功能

c# - 是否可以重写 DependencyProperty 以更改其类型并添加转换器?

c# 运行 CL exe 或批量 cpture 输出 LIVE 到文本框?

c# - 如何在 .net MVC3 中访问 javascript 函数中的 c# 变量值?

c# - 如何使用 BsonClassMap 配置 ObjectId 数组的表示形式?

python - 使用多线程 C++ 扩展时是否需要注意 Python GIL?

java - 高效执行独占执行