Использование IObservable для реализации асинхронного метода - PullRequest
3 голосов
/ 31 марта 2011

Разумно ли использовать метод, который возвращает IObservable, чтобы реализовать альтернативу стандартному асинхронному шаблону Being / End? В следующем коде я обертываю устаревший API, используя Rx, чтобы предоставить ему более приятный интерфейс.

Свойство Messages в API является hot IObservable. Моя проблема в том, что я думаю, что если я получу ответное сообщение (т. Е. m.RequestId == requestId) до того, как я верну IObservable, который фильтрует ответы, абонент не увидит его и не узнает, что операция завершена.

Есть ли способ сделать это правильно?

    public IObservable<bool> DoAsyncRequest()
    {
        Observable.Defer(delegate
        {
            int requestId = GenerateRequestId();

            this.api.DoApiRequest(requestId);

            return this.api.Messages
                .Where(m => m.RequestId == requestId)
                .Take(1)
                .Timeout(DefaultTimeout);

        });
    }

1 Ответ

3 голосов
/ 31 марта 2011

Во-первых, совершенно нормально возвращать IObservable для реализации асинхронных методов.

Во-вторых, если метод DoApiRequest запускает процесс, который генерирует значения через Messages, вы можете подписаться на сообщения, прежде чем вызывать метод с помощью CreateWithDisposable

public IObservable<bool> DoAsyncRequest()
{
    return Observable.CreateWithDisposable<bool>(observer =>
        {    
            var disposable = this.api.Messages
                .Where(m => m.RequestId == requestId)
                .Take(1)
                .Timeout(DefaultTimeout);
                .Subscribe(observer);

            int requestId = GenerateRequestId();

            this.api.DoApiRequest(requestId);

            return disposable;

        });
}

В качестве альтернативы, поскольку у вас, по-видимому, есть доступ к какому-либо классу объекта api, вы также можете изменить DoApiRequest, чтобы он возвращал холодную наблюдаемую сущность, т. Е. Возможно удалять свойство Messages и вместо этого возвращать IObservable в методе DoApiRequest.

Примечание

Если я прав, предполагая, что метод DoApiRequest запускает процесс, который генерирует значения через сообщения, то вы получите странные результаты, если этот метод вызывается несколько раз. Один вызов может получить сообщения, которые должны были быть возвращены для другого вызова. Я бы лично посмотрел на альтернативное решение, если бы вы могли.

...