3

以下是 Dispatcher 类的注释之一。

如果在后台线程上创建 Dispatcher,请确保在退出线程之前关闭 Dispatcher。

如果在后台线程上创建的调度程序上调用关闭失败,会有什么后果?

我有一个 MFC 应用程序,它在后台线程上创建一个 WPF 窗口。因此,创建了一个调度程序。当我首先关闭 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 上调用 shutdown。

不在后台线程上创建的 Dispatcher 上调用关闭将导致内存/资源泄漏。调度程序对象挂在资源上。因此,GC 无法清理它们。

为了确保调度程序正确关闭,在我的情况下,我必须从应用程序的 MFC 端生成后台线程,然后让主线程在它完全关闭之前等待它。正如 Hans Passant 所指出的,除非明确告知,否则 MFC 不会等待。

4

2 回答 2

1

如果您不关闭调度程序,线程将卡在消息循环中并且不会退出

于 2013-09-11T14:48:29.303 回答
0

在主线程中,您可以执行类似的操作

Dispatcher.FromThread(thread).InvokeShutDown();

但是,这将导致“Dispatcher.Run()”生成异常,因此您还需要将其更改为

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