Reputation: 1175
In my console app I've been trying to start an STA thread and show a WPF
window. I've succeeded showing the window, but I had issues with a library using Dispatcher
(System.Reactive.Windows.Threading
to be precised). I've fixed my problems using code from this doc - what I was missing was calling System.Windows.Threading.Dispatcher.Run()
in the right moment.
But after reading this article carefully (and others) and examining Dispatcher's
API I still don't know: how to tell WPF Dispatcher
is correctly initialized and running? It'd be very useful for libraries requiring Dispatcher
, if they could check it.
-- EDIT --
// Extending my question after @Peter Duniho remarks
Having C# console application I wanted to create a WPF window, where I'll observe, on Dispatcher, some data. The full code is here
So I have my program, where Main class looks like that:
static void Main(string[] args)
{
var observable = Observable
.Interval(TimeSpan.FromMilliseconds(500))
.TakeWhile(counter => counter < 10);
var thread = new Thread(() =>
{
new TestWindow(observable);
Dispatcher.Run();
});
thread.SetApartmentState(ApartmentState.STA);
thread.IsBackground = true;
thread.Start();
Console.ReadKey();
}
I create here an observable with Interval operator, which ticks every 500 milliseconds, and I pass it to a TestWindow (code below) which I run on a separate thread. After 10 ticks I end the observable sequence.
TestWindow
class:
public class TestWindow : Window
{
public TestWindow(IObservable<long> observable)
{
var isDispatcherInitialized = false;
Dispatcher.Invoke(() => isDispatcherInitialized = true, DispatcherPriority.ApplicationIdle);
if (!isDispatcherInitialized)
throw new ApplicationException("Dispatcher not initialized");
observable
.ObserveOnDispatcher()
.Window(TimeSpan.FromMilliseconds(600))
.Subscribe(_ => Console.WriteLine($"OnNext, observed on dispatcher with Window operator"));
}
}
In TestWindow I observe my observable on Dispatcher (ObserveOnDispatcher()
), and I use Window operator.
PROBLEM with that code (tested on .NET Framework and on .NET Core 3.0 preview):
Dispatcher.Run();
when starting STA thread, the validation where I call Dispatcher.Invoke()
will be passed, but ObserveOnDispatcher()
won't work correctly - subscription never stops, and the message: "OnNext, observed on dispatcher with Window operator" goes forever.That's why I was wondering if I could detect Dispatcher's state.
Upvotes: 2
Views: 1886
Reputation: 70671
It would be helpful if you would elaborate on this statement:
It'd be very useful for libraries requiring
Dispatcher
, if they could check it.
That is, why would it be useful?
For one, if you are using a third-party library (such as the Reactive Extensions (Rx) for .NET you mentioned, how would you knowing how to check for the dispatcher state help that library?
For another, what scenario doesn't work for you? Lacking a specific problem to solve, your question is fairly open-ended. It's not clear what type of answer would actually address your question.
That said, two things come to mind:
System.Windows.Threading.Dispatcher.FromThread(System.Threading.Thread.CurrentThread);
This will return null
if not dispatcher has been created yet for that thread, or a reference to the dispatcher if it has been.BeginInvoke()
, Invoke()
, or InvokeAsync()
) that takes a DispatcherPriority
value, you can get fine-grained information regarding just what level of initialization has happened. For example, if you pass DispatcherPriority.Normal
or DispatcherPriority.Send
, when your delegate is invoked you'll know that the dispatcher is running. But if you pass DispatcherPriority.ApplicationIdle
or DispatcherPriority.SystemIdle
, you'll know that not only is the dispatcher running, but it's cleared its backlog of initial events to dispatch and the application is sitting waiting for user input.Upvotes: 1