在WinRT上使用Rx - 在UI线程上分派

3

我目前刚开始接触Rx,在使用过程中发现它非常有用。然而,当我从异步方法创建一个可观测序列并使用结果更新UI时,遇到了问题。以下是代码:

很不幸,我遇到了RPC_E_WRONG_THREAD错误。

IDisposable service = null;

service = Observable.FromAsync(fn).Subscribe(videoColl =>
{
    foreach (var video in videoColl.Videos)
    {
        // _videos is an ObservableCollection bound to a GridView's ItemsSource property
        _videos.Add(video.SmallImageUrl);
    }
});

我看了几个类似的答案,它们建议使用 ObserveOnDispatcher 或 CoreDispatcherScheduler,但这两者都不可用。

我正在创建一个 Windows 8.1 UAP 应用程序,我通过 Nuget 获取了最新版本(2.2.5)的 Rx。我想知道这个版本是否缺少 UI 调度功能?

2个回答

4

您只需要添加 nuget 包 rx-windowstoreapps,就可以获得 CoreDispatcherSchedulerObserveOnDispatcher

然后您可以这样做:

service = Observable.FromAsync(fn)
                    .ObserveOnDispatcher()
                    .Subscribe(videoColl =>

如果您是从UI线程调用 - 我建议您在那里创建Observables,以更新UI线程。如果您无法这样做,您需要获取并保存Dispatcher的引用,然后使用.ObserveOn(dispatcher)代替(其中dispatcher是从页面或窗口等的Dispatcher属性获取的引用)。

安装 Rx-WindowStoreApp 给了我 ObserveOnDispatcher 方法,解决了线程问题。我之前安装的是 Rx-WinRT 而不是 Rx-WindowStoreApp。Rx-WindowStoreApp 包含了 Rx-WinRT 的所有内容,并且还有包含调度程序功能的 System.Reactive.Windows.Threading 程序集。 - cheneryc
是的。Rx-WindowStoreApps(注意拼写)——单数的Window,复数的Apps,是一个相当难以发现的名称,因为微软从来没有支持单窗口安装! - James World

0

不确定这是否对您有所帮助 - 但如果您缓冲事件,那么您可以使用Scheduler(并分派到UI线程):

var uiScheduler = new SynchronizationContextScheduler(SynchronizationContext.Current);
yourObservable.Buffer(SomeTimeSpan, uiScheduler).Subscribe(..)

顺便提一句 - 如果您决定缓冲观察对象,请确保在不同的Observables中使用相同的Scheduler(出于性能原因)。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接