在后台线程上创建的调度程序未关闭时会发生什么情况?如何确保调度程序已正确关闭

本文关键字:调度程序 何确保 确保 什么情况 创建 线程 后台 | 更新日期: 2023-09-27 18:30:15

以下是对调度程序类的评论之一。

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

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

我有一个 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 应用程序时它不会受到打击。 假设调度程序未关闭,但线程正在中止,这是否安全?

如果线程中止,后果是什么?

更新:

在另一个项目中,我遇到了一个问题,即 GC 似乎没有完成其工作。 事实证明,它与在未关闭的后台线程上启动的调度程序有关。 每次在后台线程上运行任务时,WPF 应用程序的内存使用量都会不断增加。 因此,无论您是否显式创建了调度程序对象,请务必在后台线程上创建的调度程序上调用关闭。

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

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

在后台线程上创建的调度程序未关闭时会发生什么情况?如何确保调度程序已正确关闭

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

在主线程中,您可以执行以下操作

Dispatcher.FromThread(thread).InvokeShutDown();

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

try
{
    System.Windows.Threading.Dispatcher.Run();
}
catch {}