Dispatcher.BeginInvoke 从不执行动作? [英] Dispatcher.BeginInvoke never execute action?

查看:37
本文介绍了Dispatcher.BeginInvoke 从不执行动作?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的操作从未执行过的代码:

I have that code where my action is never executed:

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

我没有关于Pass here..."的调试痕迹.

I have no debug traces about "Pass here...".

如果我查看作为 dispatcherOperation 的 BeginInvoke 的结果,我会得到(对于当前或以前的 dispatcherOperation):

If I look at the result of BeginInvoke which is dispatcherOperation, I get (either for current or previous dispatcherOperation):

dispatcherOperation.Status = Pending
dispatcherOperation.Task.Status = WaitingForActivation

_dispatcherOperationPrevious .Status = Pending
_dispatcherOperationPrevious .Task.Status = WaitingForActivation

为什么从不执行Debug.Print..."?

Why "Debug.Print..." is never executed?

推荐答案

这是因为在另一个线程上调用了 TimeCallback.当您在没有 Dispatcher 的线程上调用 Dispatcher.CurrentDispatcher 时,它将创建一个新的.(一个 Dispatcher 绑定到一个线程.)

This is because that the TimeCallback is called on another thread. When you call Dispatcher.CurrentDispatcher on a thread that doesn't have a Dispatcher, it will create a new one. (A Dispatcher is bound to a thread.)

因此,您正在创建一个新的调度程序,但这个新调度程序永远不会Run(),您的 Action 将在未运行的调度程序上排队.

So, you're creating a new dispatcher, but this new dispatcher is never Run() and your Action will be queued on a non running dispatcher.

我认为您想在 GUI 调度程序上调用 Action.

每个 WPF 控件都源自 DispatcherObject 并且将包含一个属性 Dispatcher ,其中包含在它们制作的地方的调度程序.使用那个.

Every WPF control is dirived from DispatcherObject and will contain a property Dispatcher containing the dispatcher on where they are made on. Use that one.

所以Dispatcher.Invoke可以理解为静态方法调用,但实际上是控件属性Dispatcher中存储的Dispatcher实例的方法调用.

So Dispatcher.Invoke could be interpreted as a static method call, but it is actually the a method call of the Dispatcher instance stored in the controls property Dispatcher.

修复:

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

如果 Dispatcher 属性在 TimeCallback 中不可用,例如,如果您在业务层深处的某些类中创建时间(不良做法),您可以调用 Application.Current.Dispatcher 获取'main/gui' Dispatcher.

If the Dispatcher property is not avaiable within the TimeCallback, for example if you created the time within some classes deep in you business layer (bad practice), you can call Application.Current.Dispatcher to get the 'main/gui' Dispatcher.

这篇关于Dispatcher.BeginInvoke 从不执行动作?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆