Асинхронная функция, выполняющая асинхронные вызовы - PullRequest
2 голосов
/ 23 августа 2011

У меня есть библиотека, которая использует асинхронный шаблон 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) без потери функциональности (обратный вызов, дескриптор ожидания, ...)?

Ответы [ 2 ]

1 голос
/ 03 сентября 2011

Чтобы иметь возможность успешно реализовать шаблон, который вы описываете, вы должны иметь возможность вызвать обратный вызов, переданный в ваш метод 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);
        }
    }
}

Предлагаю вам взглянуть на AsyncEnumerator Джеффри Рихтера.Это упрощает написание асинхронного кода и поддерживает несколько шаблонов асинхронных реализаций - http://msdn.microsoft.com/en-us/magazine/cc546608.aspx

0 голосов
/ 23 августа 2011

Используйте beginInvok для запуска асинхронной операции. Он поддерживает обратные вызовы.

Подробнее:

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...