为什么这个Observable阻塞了WPF GUI线程(C#)?

时间:2016-01-07 18:33:01

标签: c# wpf selenium system.reactive

给定:采用Selenium IWebdriver实例并返回IObservable的扩展方法

     public static IObservable<ObservableCollection<WebElementWrapper>> 
      GetAllElementsAsObservable(this IWebDriver wd)
      {
        return Observable.Create<ObservableCollection<WebElementWrapper>>(
             (IObserver<ObservableCollection<WebElementWrapper>> observer) =>
             {                     
                     var eles = wd.FindElements(By.CssSelector("*"));
                     var list = eles.ToWebElementObservableCollection();
                     observer.OnNext(list);
                     observer.OnCompleted();                     

                 return Disposable.Create(() => { });
             });
      }

调用上述方法的代码(在GUI线程上运行)......

                //GUI Will Freeze on this call until OnCompleted is called
                cd.GetAllElementsAsObservable().Subscribe((WEWList) =>
                {
                    WebElementCollection = WEWList;
                    SetNavigationItems();
                });

在调用OnCompleted之前,任何人都可以帮我确定GUI线程块的根本原因。如果我在第一个方法中使用Task.Run,​​我可以阻止阻塞,但是我必须将该集合编组回GUI线程。

这会阻塞,因为GUI线程会旋转Observable用来提取元素的Webdriver吗?

或者这是因为在GUI线程的启动时创建了静态方法?

2 个答案:

答案 0 :(得分:2)

如果你这样做 - Disposable.Create(() => { }) - 你做错了什么。使用Observable.Create的方式是阻塞操作。 .Create中的代码是订阅的一部分,但是您在订阅期间运行观察者以完成阻止。

尝试做这样的事情:

public static IObservable<ObservableCollection<WebElementWrapper>>
    GetAllElementsAsObservable(this IWebDriver wd)
{
    return Observable.Create<ObservableCollection<WebElementWrapper>>(observer =>
        Observable
            .Start(() =>
                wd
                    .FindElements(By.CssSelector("*"))
                    .ToWebElementObservableCollection())
            .Subscribe(observer));
}

答案 1 :(得分:0)

对于WPF,我也发现这两种方法有效。

SomeObservable
.SubscribeOn(Scheduler.Default)
.ObserveOn(Scheduler.CurrentThread)
.Subscribe(item => { //do something on gui thread here });

我不关心方法名称SubscribeOn,但我这样看......我希望 observable 来订阅一些调度程序。 (我认为一个更好的名字就是&#34; SheduleOn&#34;)。

ObserveOn方法名称有意义。但请注意&#34; Scheduler.Dispatcher&#34;内置物业。