WPF - Dispatcher PushFrame()

时间:2010-04-19 04:28:26

标签: wpf multithreading dispatcher

我试图从几个不同的线程调用Dispatcher.PushFrame()但遇到错误:

  

必须在同一个上创建DependencySource   线程作为DependencyObject。

以下是代码段:

_lockFrame = new DispatcherFrame(true);
Dispatcher.PushFrame(_lockFrame);

当我尝试时:

Dispatcher.CurrentDispatcher.Invoke(
    DispatcherPriority.Normal,
    new Action(() => _lockFrame = new DispatcherFrame(true));
Dispatcher.PushFrame(_lockFrame);

我收到错误:

  

对象必须由同一个创建   线程。

从不同的线程将多个帧推送到Dispatcher的方法是什么?

2 个答案:

答案 0 :(得分:15)

在不同线程的同一个调度程序上调用PushFrame是没有意义的,你没有写出你想要解决的问题,但你的基于PushFrame的解决方案可能是错误的。

Dispatcher对象负责执行单个线程的代码和调度事件,每个线程都有一个由OS发送的消息队列,并包含鼠标点击之类的通知,调度程序有一个读取此队列的循环并调用适当的事件。

有时您必须处理消息而不从方法返回到调度程序循环,这是一个很好的示例,它是响应用户输入的模态对话框(因此它们需要处理消息)而不会中断调用的方法的控制流它们。

PushFrame的作用 - 它在你的代码中运行调度程序循环。

每个线程(可选)都有自己的消息队列,消息特定于属于该线程的窗口和控件,不能从另一个线程处理线程的消息队列(Windows本身没有API)这让你读另一个帖子的消息。)

从另一个线程调用PushFrame是行不通的,因为你的调用发生在错误的线程上,PushFrame本身必须在调度程序管理的同一个线程上调用,你不能在另一个线程上调用它,因为那是在尝试在另一个线程上处理线程的消息。

使用Invoke或BeginInvoke在这里也没有意义,因为只有在调度程序正在处理消息时才会调用传递给这些方法的委托,如果调度正在处理消息,则不需要调用PushFrame来使其处理消息。

如果你问另一个问题,描述你想要做什么,这里有人可能会帮助你,但从不同的线程调用Dispatcher.PushFrame永远不会起作用。

答案 1 :(得分:1)

每个线程都有自己的调度程序对象 - 由Dispatcher.CurrentDispatcher

返回

方法是通过在UI线程上调用上述方法来缓存目标调度程序对象一次。然后像你一样使用_cachedObj.Invoke - 将它编组到正确的线程中。

WPF UI具有“线程关联性” - UI只能由创建它的线程访问。

更新:不确定您要实现的目标。但是下面的代码片段对我有用。

    private Dispatcher _dispatcher;
    private DispatcherFrame _lockFrame;
    public Window1()
    {
        InitializeComponent();

        _dispatcher = Dispatcher.CurrentDispatcher;

        // the other thread
        Thread t = new Thread(
            (ThreadStart)delegate
            {

                _dispatcher.Invoke(
                    (Action)delegate
                    {
                        var frame = CreateNewFrame();
                        Dispatcher.PushFrame(frame);
                    });
            });
        t.Start();