如何告诉Dispatcher 已经初始化并且运行?
How to tell Dispatcher is initialized and running?
在我的控制台应用程序中,我一直在尝试启动 STA 线程并显示 WPF
window。我已经成功地显示了 window,但是我在使用 Dispatcher
(准确地说是 System.Reactive.Windows.Threading
)的库中遇到了问题。我已经使用 this doc 中的代码解决了我的问题 - 我缺少的是在正确的时刻调用 System.Windows.Threading.Dispatcher.Run()
。
但是在仔细阅读这篇文章(和其他文章)并检查 Dispatcher's
API 之后,我仍然不知道:如何判断 WPF Dispatcher
是否正确初始化和 运行宁?如果需要 Dispatcher
的图书馆可以检查它,这将非常有用。
-- 编辑--
// 在@Peter Duniho 评论后扩展我的问题
有了 C# 控制台应用程序,我想创建一个 WPF window,我将在其中观察 Dispatcher 上的一些数据。完整代码为here
所以我有我的程序,其中 Main class 看起来像这样:
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
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"));
}
}
在测试Window中,我在 Dispatcher (ObserveOnDispatcher()
) 上观察我的可观察对象,并且我使用 Window 运算符。
该代码存在问题(在 .NET Framework 和 .NET Core 3.0 预览版上测试):
- 如果我在启动 STA 线程时不调用
Dispatcher.Run();
,我调用 Dispatcher.Invoke()
的验证将通过,但 ObserveOnDispatcher()
将无法正常工作 - 订阅永远不会停止,并且消息:“OnNext,使用 Window 运算符在调度程序上观察到”永远存在。
这就是为什么我想知道是否可以检测 Dispatcher 的状态。
如果您能详细说明此声明,将会很有帮助:
It'd be very useful for libraries requiring Dispatcher
, if they could check it.
也就是说,它为什么会有用?
首先,如果您使用的是第三方库(例如您提到的 Reactive Extensions (Rx) for .NET,您怎么知道如何检查调度程序状态帮助该库?
另外,哪种情况不适合?缺乏要解决的具体问题,您的问题是相当开放的。目前尚不清楚哪种类型的答案会真正解决您的问题。
也就是说,我想到了两件事:
- 如果您想知道是否已为给定线程创建 调度程序,您应该调用
System.Windows.Threading.Dispatcher.FromThread(System.Threading.Thread.CurrentThread);
这将return null
如果尚未为该线程创建调度程序,或者如果已经创建调度程序的引用。
- 如果你想知道调度器已经完成初始化并准备好调度东西,在我看来最简单的事情就是让它调度一些东西,当它调度时,它就准备好了。使用采用
DispatcherPriority
值的其中一种调用方法(BeginInvoke()
、Invoke()
或 InvokeAsync()
)的重载,您可以获得有关级别的详细信息初始化已经发生。例如,如果您传递 DispatcherPriority.Normal
或 DispatcherPriority.Send
,当您的委托被调用时,您将知道调度程序是 运行。但是如果你传递 DispatcherPriority.ApplicationIdle
或 DispatcherPriority.SystemIdle
,你会知道不仅是调度程序 运行,而且它已经清除了要调度的初始事件的积压并且应用程序正在等待用户输入。
在我的控制台应用程序中,我一直在尝试启动 STA 线程并显示 WPF
window。我已经成功地显示了 window,但是我在使用 Dispatcher
(准确地说是 System.Reactive.Windows.Threading
)的库中遇到了问题。我已经使用 this doc 中的代码解决了我的问题 - 我缺少的是在正确的时刻调用 System.Windows.Threading.Dispatcher.Run()
。
但是在仔细阅读这篇文章(和其他文章)并检查 Dispatcher's
API 之后,我仍然不知道:如何判断 WPF Dispatcher
是否正确初始化和 运行宁?如果需要 Dispatcher
的图书馆可以检查它,这将非常有用。
-- 编辑--
// 在@Peter Duniho 评论后扩展我的问题
有了 C# 控制台应用程序,我想创建一个 WPF window,我将在其中观察 Dispatcher 上的一些数据。完整代码为here
所以我有我的程序,其中 Main class 看起来像这样:
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
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"));
}
}
在测试Window中,我在 Dispatcher (ObserveOnDispatcher()
) 上观察我的可观察对象,并且我使用 Window 运算符。
该代码存在问题(在 .NET Framework 和 .NET Core 3.0 预览版上测试):
- 如果我在启动 STA 线程时不调用
Dispatcher.Run();
,我调用Dispatcher.Invoke()
的验证将通过,但ObserveOnDispatcher()
将无法正常工作 - 订阅永远不会停止,并且消息:“OnNext,使用 Window 运算符在调度程序上观察到”永远存在。
这就是为什么我想知道是否可以检测 Dispatcher 的状态。
如果您能详细说明此声明,将会很有帮助:
It'd be very useful for libraries requiring
Dispatcher
, if they could check it.
也就是说,它为什么会有用?
首先,如果您使用的是第三方库(例如您提到的 Reactive Extensions (Rx) for .NET,您怎么知道如何检查调度程序状态帮助该库?
另外,哪种情况不适合?缺乏要解决的具体问题,您的问题是相当开放的。目前尚不清楚哪种类型的答案会真正解决您的问题。
也就是说,我想到了两件事:
- 如果您想知道是否已为给定线程创建 调度程序,您应该调用
System.Windows.Threading.Dispatcher.FromThread(System.Threading.Thread.CurrentThread);
这将returnnull
如果尚未为该线程创建调度程序,或者如果已经创建调度程序的引用。 - 如果你想知道调度器已经完成初始化并准备好调度东西,在我看来最简单的事情就是让它调度一些东西,当它调度时,它就准备好了。使用采用
DispatcherPriority
值的其中一种调用方法(BeginInvoke()
、Invoke()
或InvokeAsync()
)的重载,您可以获得有关级别的详细信息初始化已经发生。例如,如果您传递DispatcherPriority.Normal
或DispatcherPriority.Send
,当您的委托被调用时,您将知道调度程序是 运行。但是如果你传递DispatcherPriority.ApplicationIdle
或DispatcherPriority.SystemIdle
,你会知道不仅是调度程序 运行,而且它已经清除了要调度的初始事件的积压并且应用程序正在等待用户输入。