ReactiveExtensions和异步服务方法?

时间:2014-05-21 16:13:00

标签: c# wcf task .net-4.5 system.reactive

我在使用ReactiveExtensions时遇到了麻烦(可能很难理解),我在WinForms应用程序中连接了一个WCF服务,从以下教程开始,这就是我想出来的,而这从来没有工作过,所以我将它从常规同步方法改为异步方法,我开始改为语法错误。当我订阅它时,为什么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;

2 个答案:

答案 0 :(得分:4)

您获得Observable<T[]>的原因是因为ToObservable上的Task<T>返回Observable<T>。必须这样做才能确保任何类型的任务都可以转换为Observable。在这种情况下,Task用于表示返回单个值的异步函数。 Observable用于表示具有多个值的异步函数。因此,当我们将Task转换为Observable时,我们转换一个异步函数,只能返回一个值 - &gt;一个异步函数,只会返回一个值。

因此,一旦我们有一个只返回一个值的异步函数,并且该值是一个可以包含多个值的对象,我们必须创建另一个异步函数,它返回对象中包含的所有值。为此,我们可以使用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只是意味着&#34;一次合并事物&#34 ;.)

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>,因为没有超载这样做。但是,没有重载的原因是因为它会阻止用户使用Observableawait一系列事物。

答案 1 :(得分:1)

我认为如果你查看ToObservable扩展方法将任务转换为observable,这应该很简单。

看起来像这样:

IObservable<TResult> ToObservable<TResult>(this Task<TResult> task)

因此,如果您从Task<T[]>开始,那么您将获得IObservable<T[]>

因此,例如,这有:

Task<int[]> task = Task.Run(() => new [] { 1, 2, 3 });

IObservable<int[]> observable = task.ToObservable();

现在,如果你想获得IObservable<int>,那么你需要这样做:

IObservable<int> observable2 = observable.SelectMany(x => x);