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