3

以下は、Dispatcher クラスに関する注意事項の 1 つです。

バックグラウンド スレッドで Dispatcher を作成する場合は、スレッドを終了する前に必ず Dispatcher をシャットダウンしてください。

バックグラウンド スレッドで作成されたディスパッチャーでシャットダウンの呼び出しに失敗した場合、どのような結果になりますか?

バックグラウンド スレッドで WPF ウィンドウを作成する MFC アプリケーションがあります。その結果、ディスパッチャーが作成されます。最初に WPF ウィンドウを閉じると、ディスパッチャでシャットダウンを明示的に呼び出すことができますが、MFC アプリケーションを閉じると、WPF ウィンドウも一緒に閉じます。

ディスパッチャが暗黙的にシャットダウンされているか、スレッドが中止されているようです。それはどれですか?

アップデート:

次のメソッドは、新しいスレッドを作成し、wpf ウィンドウを開きます。

public void ShowWindow(SomeObject someObject)
{
    System.Threading.Thread thread = new System.Threading.Thread((tuple) =>
        {
            Tuple<Dispatcher, SomeObject> data = tuple as Tuple<Dispatcher, SomeObject>;
            Window window = new WPFWindow(data.Item1, data.Item2);
            System.Windows.Threading.Dispatcher.Run();
            this.tmp = 0;
        });
    thread.SetApartmentState(System.Threading.ApartmentState.STA);
    thread.IsBackground = true;
    thread.Start(new Tuple<Dispatcher, SomeObject>(Dispatcher.CurrentDispatcher, someObject));
}

そこで、「this.tmp = 0;」という文に沿って区切りをつけます。MFCアプリケーションを閉じてもヒットしません。Dispatcher はシャットダウンされていませんが、スレッドは中止されていると想定しても安全ですか?

スレッドが中止された場合、結果はどうなりますか?

アップデート:

別のプロジェクトで、GC が機能していないように見える問題に遭遇しました。シャットダウンされていないバックグラウンド スレッドで開始された Dispatcher に関連していることが判明しました。タスクがバックグラウンド スレッドで実行されるたびに、WPF アプリケーションのメモリ使用量が増え続けていました。そのため、Dispatcher オブジェクトを明示的に作成したかどうかに関係なく、バックグラウンド スレッドで作成された Dispatcher でシャットダウンを呼び出すようにしてください。

バックグラウンド スレッドで作成された Dispatcher でシャットダウンを呼び出さないと、メモリ/リソース リークが発生します。Dispatcher オブジェクトはリソースに依存します。したがって、GC はそれらをクリーンアップできません。

私の場合、ディスパッチャが適切にシャットダウンされるようにするには、アプリケーションの MFC 側からバックグラウンド スレッドを生成し、完全にシャットダウンする前にメイン スレッドを待機させる必要があります。Hans Passant が指摘したように、MFC は明示的に指示されない限り待機しません。

4

2 に答える 2

0

メインスレッドでは、次のようなことができます

Dispatcher.FromThread(thread).InvokeShutDown();

ただし、これにより「Dispatcher.Run()」が例外を生成するため、これを次のように変更する必要もあります。

try
{
    System.Windows.Threading.Dispatcher.Run();
}
catch {}
于 2020-08-30T21:01:45.283 に答える