1

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

必须在与 DependencyObject 相同的线程上创建 DependencySource。

这是一个代码片段:

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

当我尝试时:

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

我得到错误:

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

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

4

2 回答 2

15

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

Dispatcher 对象负责为单个线程执行代码和调度事件,每个线程都有一个由操作系统发送的消息队列,包括鼠标点击等通知,调度程序有一个循环读取这个队列并调用适当的事件。

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

这就是 PushFrame 所做的 - 它在您的代码中运行调度程序循环。

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

从另一个线程调用 PushFrame 无法正常工作,因为您调用发生在错误的线程上,PushFrame 本身必须在调度程序管理的同一线程上调用,您不能在另一个线程上调用它,因为它正在尝试处理线程的消息在另一个线程上。

在这里使用 Invoke 或 BeginInvoke 也没有意义,因为传递给这些方法的委托仅在调度程序处理消息时调用,如果调度程序已经在处理消息,则无需调用 PushFrame 使其处理消息。

如果您问另一个描述您正在尝试做什么的问题,这里的某人可能会帮助您,但是从不同的线程调用 Dispatcher.PushFrame 永远不会起作用。

于 2010-04-19T06:29:44.023 回答
2

每个线程都有自己的调度程序对象 - 由 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();
于 2010-04-19T05:04:32.543 回答