У меня возникают проблемы (возможно, проблемы с пониманием) с помощью ReactiveExtensions, у меня есть служба WCF, с которой я подключаюсь в приложении WinForms, и из следующих руководств. Это то, что я придумал, и это никогда не срабатывало, поэтому я изменил его с регулярные синхронные методы для асинхронных, я вместо этого начал синтаксические ошибки. Почему Task<T[]>.ToObservable()
дает мне T[]
когда я подписываюсь на него? У меня может быть намного больше, чем это неправильно. Спасибо за любую помощь!
var users =
_chatServiceClient.GetAllUsersAsync()
.ToObservable()
.SubscribeOn(TaskPoolScheduler.Default)
.ObserveOn(this)
.Throttle(TimeSpan.FromMilliseconds(500))
.DistinctUntilChanged();
var messages =
_chatServiceClient.GetNewMessagesAsync(_me)
.ToObservable()
.SubscribeOn(TaskPoolScheduler.Default)
.ObserveOn(this)
.DistinctUntilChanged()
.Throttle(TimeSpan.FromMilliseconds(100))
.Subscribe(m => chatRichTextBox.AppendText(string.Format("{0}:{1}: {2}", m.Date, m.User, m.Content)));
userList.DataSource = users;
Причина, по которой вы получаете Observable<T[]>
заключается в том, что ToObservable
в Task<T>
возвращает Observable<T>
. Он должен сделать это, чтобы любой тип задачи мог быть преобразован в Observable
. В этом случае задача используется для представления асинхронной функции, которая возвращает одно значение. Observable используется для представления асинхронной функции с несколькими значениями. Итак, когда мы конвертируем задачу в наблюдаемую, мы преобразуем асинхронную функцию, которая может возвращать только одно значение → асинхронную функцию, которая будет возвращать только одно значение.
Поэтому, если у нас есть асинхронная функция, которая возвращает только одно значение, и это значение является объектом, который может содержать несколько значений, мы должны создать другую асинхронную функцию, которая возвращает все значения, содержащиеся в объекте. Для этого мы можем использовать SelectMany
.
Task<T[]> taskOfCollection = ...;
Observable<T[]> obsOfCollection = TaskOfCollection.ToObservable();
Observable<T> obsOfItems = obsOfCollection.SelectMany(x => x.ToObservable());
Однако, поскольку x
является массивом, он является Enumerable
, а SelectMany
знает, как обрабатывать Enumerable
, поэтому мы можем просто вернуть x
.
Observable<T> obsOfItems = obsOfCollection.SelectMany(x => x);
Вышесказанное - это просто длинный способ Merge
.
Observable<T> obsOfItems = obsOfCollection.Merge();
И поскольку из obsOfCollection возвращается только один элемент, Concat
работает тоже (Concat
просто означает "Слияние на предмет за раз").
Observable<T> obsOfItems = obsOfCollection.Concat();
Итак, ваше окончательное выражение становится следующим:
Observable<T> obs = task.ToObservable().Merge();
// or
Observable<T> obs = task.ToObservable().Merge(1);
// or
Observable<T> obs = task.ToObservable().Concat();
Причина ToObservable
в Task<T[]>
не возвращает Observable<T>
, потому что для этого нет перегрузки. Однако причина, по которой перегрузка не возникает, заключается в том, что она не позволит пользователям использовать Observable
для await
множества вещей.
Я думаю, что это должно быть достаточно простым, если вы посмотрите на ToObservable
расширения ToObservable
для преобразования задачи в наблюдаемую.
Это выглядит так:
IObservable<TResult> ToObservable<TResult>(this Task<TResult> task)
Поэтому, если вы начинаете с Task<T[]>
тогда вы получите IObservable<T[]>
out.
Так, например, это имеет место:
Task<int[]> task = Task.Run(() => new [] { 1, 2, 3 });
IObservable<int[]> observable = task.ToObservable();
Теперь, если вы хотите получить IObservable<int>
, вам нужно сделать следующее:
IObservable<int> observable2 = observable.SelectMany(x => x);