C# Dispatcher.BeginInvoke是否从不执行操作?
我有一段代码,我的操作从未执行过:C# Dispatcher.BeginInvoke是否从不执行操作?,c#,wpf,multithreading,timer,dispatcher,C#,Wpf,Multithreading,Timer,Dispatcher,我有一段代码,我的操作从未执行过: private static Timer timer = new Timer(TimerCallback, null, 5000, 5000); private static DispatcherOperation dispatcherOperationPrevious = null; private static void TimerCallback(object state) { DispatcherOperation dispatcherOper
private static Timer timer = new Timer(TimerCallback, null, 5000, 5000);
private static DispatcherOperation dispatcherOperationPrevious = null;
private static void TimerCallback(object state)
{
DispatcherOperation dispatcherOperation =
Dispatcher.CurrentDispatcher.BeginInvoke(new Action(() =>
{
Debug.Print("Pass here at: " + DateTime.Now.ToString("O"));
}));
dispatcherOperationPrevious = dispatcherOperation;
}
我没有关于“在这里传递…”的调试跟踪
如果我查看BeginInvoke的结果,即dispatcherOperation,我会得到(对于当前或以前的dispatcherOperation):
为什么从不执行“Debug.Print…”?这是因为在另一个线程上调用了TimeCallback。在没有调度程序的线程上调用Dispatcher.CurrentDispatcher时,它将创建一个新的调度程序。(调度程序绑定到线程。) 因此,您正在创建一个新的dispatcher,但是这个新的dispatcher永远不会
Run()
,您的操作将在一个非运行的dispatcher上排队
我想您需要调用GUI调度程序上的操作。
每个WPF控件都由DispatcherObject
驱动,并将包含一个属性Dispatcher
,该属性包含在其上创建的Dispatcher。用那个
因此,Dispatcher.Invoke
可以解释为静态方法调用,但它实际上是存储在控件属性Dispatcher中的Dispatcher实例的方法调用
修正:
如果调度程序属性在TimeCallback中不可用,例如,如果您在业务层深处的某些类中创建了时间(错误做法),则可以调用Application.Current.Dispatcher
以获取“main/gui”调度程序。如本文所述,Dispatcher.CurrentDispatcher
将从当前线程获取Dispatcher
,在您的情况下,该线程是计时器的线程。如果要从GUI线程调用调试调用,则需要使用Application.CurrentDispatcher
private static void TimerCallback(object state)
{
DispatcherOperation dispatcherOperation =
Application.CurrentDispatcher.BeginInvoke(new Action(() =>
{
Debug.Print("Pass here at: " + DateTime.Now.ToString("O"));
}));
dispatcherOperationPrevious = dispatcherOperation;
}
不过,我不建议使用标准的计时器
,而建议使用调度程序。dispatchermer
设计用于更新UI(无需显式调用)
如果在WPF应用程序中使用System.Timers.Timer,那么它是值得的
注意System.Timers.Timer运行在不同的线程上
用户界面(UI)线程。以访问用户上的对象
接口(UI)线程,有必要将操作发布到
使用Invoke或
开始觉醒。使用Dispatchermer而不是
System.Timers.Timer是调度程序在同一台计算机上运行的
线程作为Dispatcher,并且可以在上设置DispatcherPriority
调度员
我收到了两个极好的答案。我得选一个。我随机挑选了一些。我投了你的票。非常感谢。非常清楚,非常感谢。解释清楚。
private static Timer timer = new Timer(TimerCallback, null, 5000, 5000);
private static DispatcherOperation dispatcherOperationPrevious = null;
private static void TimerCallback(object state)
{
DispatcherOperation dispatcherOperation =
// Dispatcher here is using the controls dispatcher, the BeginInvoke is not a static method.. (like you probably assumed..
// So calling the BeginInvoke of the controls property 'Dispatcher'
Dispatcher.BeginInvoke(new Action(() =>
{
Debug.Print("Pass here at: " + DateTime.Now.ToString("O"));
}));
dispatcherOperationPrevious = dispatcherOperation;
}
private static void TimerCallback(object state)
{
DispatcherOperation dispatcherOperation =
Application.CurrentDispatcher.BeginInvoke(new Action(() =>
{
Debug.Print("Pass here at: " + DateTime.Now.ToString("O"));
}));
dispatcherOperationPrevious = dispatcherOperation;
}