Многоуровневая модель вызова асинхронного метода в c # - PullRequest
1 голос
/ 10 июня 2010

У меня проблема с дизайном в отношении асинхронных вызовов метода.

Я хотел бы знать лучший / хороший шаблон вызова асинхронного метода, который вызывает другой асинхронный метод, который вызывает другой асинхронный метод :)

Другими словами, у меня есть ссылка на службу WCF, созданная с помощью асинхронных методов, и я хочу вызвать их из другого асинхронного метода, который вызывается другим асинхронным методом.Все это для неблокирующего GUI.

Спасибо!

Ответы [ 3 ]

3 голосов
/ 10 июня 2010

Если ваша единственная цель - иметь неблокирующий графический интерфейс, тогда несколько уровней не нужны. Как только ваш метод верхнего уровня запускается в фоновом режиме, ваш графический интерфейс освобождается. Использование нескольких уровней приносит дополнительную сложность.

Могут быть и другие причины (производительность) для вызова методов более низкого уровня асинхронными, но это зависит. Вам нужно ждать результатов позже?

Так что я не думаю, что здесь есть «образец».

0 голосов
/ 12 января 2016

Недавно я разработал реализацию хранилища атрибутов ADFS, которое вызывает внутренний веб-сервис для извлечения данных.Я хотел следовать подходу фабрики -> клиента, а не использовать его повторно для каждого вызова, поэтому я остановился на двухуровневых асинхронных вызовах, как показано в упрощенном примере кода ниже:

public class IMyAttributeStore : IAttributeStore
{
    ChannelFactory<IMyBackendInterface> factory;
    public IMyAttributeStore()
    {
    }

    public IAsyncResult BeginExecuteQuery(string query, string[] parameters, AsyncCallback callback, object state)
    {
        AsyncResult queryResult = new TypedAsyncResult<string[][]>(callback, state);
        var client = factory.CreateChannel();
        CallState cs = new CallState(client, queryResult);

        Request rq = new Request();

        client.BeginGetUserRoles(rq, new AsyncCallback(AsyncCallCallback), cs);

        return cs.result;
    }

    public string[][] EndExecuteQuery(IAsyncResult result)
    {
        return TypedAsyncResult<string[][]>.End(result);
    }

    // Initialize state here.
    public void Initialize(Dictionary<string, string> config)
    {
        var endpoint = config["endpointConfigurationName"];
        factory = new ChannelFactory<IMyBackendInterface>(endpoint);
    }

    void AsyncCallCallback(IAsyncResult result)
    {
        CallState cs = (CallState)result.AsyncState;

        Response data = cs.client.EndGetUserRoles(result);
        List<string[]> claimData = new List<string[]>();
        foreach (var val in data.Values)
            claimData.Add(new string[1] { val });
        string[][] retVal = claimData.ToArray();

        TypedAsyncResult<string[][]> queryResult = (TypedAsyncResult<string[][]>)cs.result;
        queryResult.Complete(retVal, false);
    }
}

class CallState
{
    public IMyBackendInterface client;
    public AsyncResult result;

    public CallState(IMyBackendInterface c, AsyncResult r)
    {
        client = c;
        result = r;
    }
}

Интересно, если это хороший шаблонследовать, или кто-то тем временем узнал лучше?

0 голосов
/ 14 сентября 2010

Одним из примеров, когда было бы хорошо иметь несколько уровней, было бы создание асинхронных контроллеров в среде MVC, такой как MonoRail или MS MVC. Конечная вещь, которая вызывает блокировку ввода-вывода, например SqlCommand из System.Data.SqlClient или какого-либо сокета, помещает операнд ввода-вывода в порт завершения ввода-вывода: http://msdn.microsoft.com/library/aa365198,, что позволяет сохранить кванты управляемого / неуправляемого потока для чего-то более полезного.

Если вы пишете классы, которые возвращают IAsyncResult, то вы не далеко от реализации сопрограмм. Вот хорошая статья о том, как асинхронное программирование может использоваться с сопрограммами: http://blogs.msdn.com/b/pfxteam/archive/2009/06/30/9809774.aspx.

Caliburn, инфраструктура WPF изначально поддерживает сопрограммы. Библиотека параллельных задач, выпущенная с .Net 4, дала своей задаче интерфейс IAsyncResult. [Если вы находитесь на уровне 3.5, вам может потребоваться создать собственную реализацию (их довольно просто сделать, просто реализуйте интерфейс).] Совместные подпрограммы - это способ использования перезаписей компилятора IEnumerable для передачи IAsyncResults в стек вещей, которые нужно сделать (как видно из «асинхронного менеджера»).

F # async (как видно в ответе с отрицательным голосом) использует монаду (такую ​​же, как они попадают в CLR) для перемещения состояния асинхронного запроса из методов Begin * в End *. Оба компилятора это вложенные лямбда-выражения / SelectMany.

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