Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is this Observable blocking the WPF GUI thread (C#)?

Given: An extension method taking a Selenium IWebdriver instance and returning an 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(() => { });
             });
      }

And the code that calls the method above (running on GUI thread)...

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

Can anyone help me determine root cause of GUI thread block until OnCompleted is called. I can stop the blocking if I use Task.Run in first method, but then I have to marshall the collection back onto GUI thread.

Does this block because the GUI thread spun up the Webdriver of which the Observable is using to extract elements?

Or is this due to the static methods being created at start up time on the GUI thread?

like image 375
JWP Avatar asked Dec 31 '25 02:12

JWP


1 Answers

If ever you do this - Disposable.Create(() => { }) - you are doing something wrong. Using Observable.Create the way you are using it is a blocking operation. The code inside the .Create is part of the subscription, but you're running the observer to completion during subscription which is why it is blocking.

Try doing something like this instead:

public static IObservable<ObservableCollection<WebElementWrapper>>
    GetAllElementsAsObservable(this IWebDriver wd)
{
    return Observable.Create<ObservableCollection<WebElementWrapper>>(observer =>
        Observable
            .Start(() =>
                wd
                    .FindElements(By.CssSelector("*"))
                    .ToWebElementObservableCollection())
            .Subscribe(observer));
}
like image 134
Enigmativity Avatar answered Jan 02 '26 15:01

Enigmativity



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!