异步函数进行异步调用

发布于 2024-11-30 20:25:20 字数 1051 浏览 1 评论 0原文

我有一个使用 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 中)的最简洁方法是什么?

I have a library that uses the BeginXxx EndXxx asynchronous pattern (obviously, the following code is simplified):

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

I'm trying to build a class that uses that library, and that implements the same pattern itself:

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)
    {
        //???
    }
}

I've tried a couple of solutions (using ManualResetEvent) but I find my code very ugly. What is the cleanest way to do this (in C#3.5) without losing functionality (callback, wait handle, ...)?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

傾城如夢未必闌珊 2024-12-07 20:25:20

为了能够成功实现您所描述的模式,您应该能够在所有单个操作完成后调用传递到 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

To be able to successfully implement the pattern you are describing, you should be able to call the callback passed into your BeginMultipleActions method after all single actions are complete. Using events and waiting on them, might defeat your sole purpose of doing async calls as they would block the threads. The callback you pass into the single action should be able to figure out when all the methods are completed and then call the callback supplied by your client to the BeginMultipleActions method. Here's a sample that might do it for you (I haven't tested it). However, this is only to get you started and is far from perfect. There will be several nuances that you will have to work through.

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

I suggest you take a look at Jeffrey Richter's AsyncEnumerator. It simplifies writing asynchronous code and supports several patterns of async implementations - http://msdn.microsoft.com/en-us/magazine/cc546608.aspx

永不分离 2024-12-07 20:25:20

使用 beginInvok 启动异步操作。它支持回调。

更多详细信息:

http://msdn.microsoft.com/en-us/library/ 2e08f6yc.aspx

Use beginInvok for start asincronous operation. It supports callbacks.

More detail:

http://msdn.microsoft.com/en-us/library/2e08f6yc.aspx

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文