如何判断调度程序已初始化并正在运行?



在我的控制台应用程序中,我一直在尝试启动 STA 线程并显示WPF窗口。我已经成功地展示了窗口,但是使用Dispatcher的库遇到了问题(准确地说是System.Reactive.Windows.Threading(。我已经使用此文档中的代码解决了我的问题 - 我缺少的是System.Windows.Threading.Dispatcher.Run()在适当的时候打电话给。

但是在仔细阅读本文(和其他文章(并检查Dispatcher'sAPI 后,我仍然不知道:如何判断WPF Dispatcher已正确初始化并正在运行?对于需要Dispatcher的库来说,如果他们可以检查的话,这将是非常有用的。

--编辑--

杜尼奥@Peter言论后扩展我的问题

有了 C# 控制台应用程序,我想创建一个 WPF 窗口,我将在其中观察调度程序上的一些数据。完整代码在这里

所以我有我的程序,其中主类看起来像这样:

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();
}

我在这里创建了一个带有 Interval 运算符的可观察量,它每 500 毫秒滴答一次,并将其传递给我在单独的线程上运行的 TestWindow(下面的代码(。在 10 次刻度后,我结束了可观察的序列。

TestWindow类:

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"));
}
}

在测试窗口中,我在调度程序(ObserveOnDispatcher()(上观察我的可观察量,并且我使用窗口运算符。

该代码的问题(在.NET Framework和.NET Core 3.0预览版上测试(:

  • 如果我在启动 STA 线程时不调用Dispatcher.Run();,则我调用Dispatcher.Invoke()的验证将通过,但ObserveOnDispatcher()将无法正常工作 - 订阅永远不会停止,并且消息:"OnNext,使用 Window 运算符在调度程序上观察到"将永远存在。

这就是为什么我想知道我是否可以检测到调度程序的状态。

如果您详细说明此声明,将会很有帮助:

对于需要Dispatcher的库来说,如果他们可以检查的话,这将是非常有用的。

也就是说,为什么它会有用?

首先,如果您使用的是第三方库(例如您提到的 .NET 的反应式扩展 (Rx(,您如何知道如何检查调度程序状态对该库的帮助?

另一方面,什么场景不适合你?由于缺乏要解决的具体问题,您的问题相当开放。目前尚不清楚哪种类型的答案可以真正解决您的问题。

也就是说,我想到了两件事:

  1. 如果您想知道是否已为给定线程创建了调度程序,则应调用System.Windows.Threading.Dispatcher.FromThread(System.Threading.Thread.CurrentThread);如果尚未为该线程创建调度程序,这将返回null,如果已创建调度程序,则返回对调度程序的引用。
  2. 如果你想知道调度程序已经完成初始化并准备好调度东西,在我看来,最简单的办法就是要求它调度一些东西,当它这样做时,它就准备好了。使用一个调用方法(BeginInvoke()Invoke()InvokeAsync()(的重载来获取DispatcherPriority值,你可以得到关于初始化级别发生的细粒度信息。例如,如果您传递DispatcherPriority.NormalDispatcherPriority.Send,则在调用委托时,您将知道调度程序正在运行。但是,如果您传递DispatcherPriority.ApplicationIdleDispatcherPriority.SystemIdle,您将知道调度程序不仅正在运行,而且还清除了要调度的初始事件的积压工作,并且应用程序正在等待用户输入。

相关内容

  • 没有找到相关文章

最新更新