1

いくつかの異なるスレッドから Dispatcher.PushFrame() を呼び出そうとしていますが、エラーが発生します:

DependencyObject と同じ Thread に 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 オブジェクトは、コードの実行と 1 つのスレッドのイベントのディスパッチを担当します。各スレッドには、OS によって送信されるメッセージのキューがあり、マウス クリックなどの通知が含まれます。ディスパッチャーには、このキューを読み取り、適切なイベント。

メソッドからディスパッチャ ループに戻らずにメッセージを処理しなければならない場合があります。これの良い例は、呼び出し元のメソッドの制御フローを中断せずにユーザー入力に応答する (メッセージを処理する必要がある) モーダル ダイアログです。

PushFrame が行うこと - コード内でディスパッチャ ループを実行します。

各スレッドには (オプションで) 独自のメッセージ キューがあり、メッセージはそのスレッドに属するウィンドウとコントロールに固有であり、スレッドのメッセージ キューを別のスレッドから処理することはできません (Windows 自体には、それを可能にする API がありません)。別のスレッドのメッセージを読む)。

呼び出しが間違ったスレッドで発生しているため、別のスレッドから PushFrame を呼び出すことはできません。PushFrame 自体は、ディスパッチャによって管理される同じスレッドで呼び出す必要があります。別のスレッドで呼び出すことはできません。スレッドのメッセージを別のスレッドに。

Invoke または BeginInvoke を使用しても、ここでは意味がありません。これらのメソッドに渡されたデリゲートは、ディスパッチャーがメッセージを処理しているときにのみ呼び出されるためです。ディスパッチャーが既にメッセージを処理している場合は、PushFrame を呼び出してメッセージを処理させる必要はありません。

あなたが何をしようとしているのかを説明する別の質問をする場合、ここの誰かがあなたを助けることができるかもしれませんが、別のスレッドから Dispatcher.PushFrame を呼び出すことは決してうまくいきません.

于 2010-04-19T06:29:44.023 に答える
2

各スレッドには、Dispatcher.CurrentDispatcher によって返される独自のディスパッチャ オブジェクトがあります。

アプローチは、UI スレッドで上記のメソッドを呼び出して、ターゲット ディスパッチャ オブジェクトを 1 回キャッシュすることです。次に、_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 に答える