Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/apache-spark/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 在后台线程上创建的调度程序未关闭时会发生什么情况?如何确保调度器正确关闭?_C#_C++_Wpf_Multithreading_Mfc - Fatal编程技术网

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

C# 在后台线程上创建的调度程序未关闭时会发生什么情况?如何确保调度器正确关闭?,c#,c++,wpf,multithreading,mfc,C#,C++,Wpf,Multithreading,Mfc,下面是关于Dispatcher类的注释之一 如果在后台线程上创建调度程序,请确保在退出线程之前关闭调度程序 如果在后台线程上创建的调度程序上调用SHUTDOWN失败,会产生什么后果 我有一个MFC应用程序,它在后台线程上创建一个WPF窗口。因此,将创建一个调度程序。当我首先关闭WPF窗口时,我可以显式地调用dispatcher上的shutdown,但是当我关闭MFC应用程序时,WPF窗口也随之关闭 调度程序似乎被隐式关闭,或者线程被中止。是哪一个 更新: 下面的方法创建一个新线程并打开wpf窗口

下面是关于Dispatcher类的注释之一

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

如果在后台线程上创建的调度程序上调用SHUTDOWN失败,会产生什么后果

我有一个MFC应用程序,它在后台线程上创建一个WPF窗口。因此,将创建一个调度程序。当我首先关闭WPF窗口时,我可以显式地调用dispatcher上的shutdown,但是当我关闭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));
}
public void显示窗口(SomeObject SomeObject)
{
System.Threading.Thread线程=新的System.Threading.Thread((元组)=>
{
元组数据=作为元组的元组;
窗口窗口=新WPFWindow(data.Item1,data.Item2);
System.Windows.Threading.Dispatcher.Run();
该值为0.tmp=0;
});
SetApartmentState(System.Threading.ApartmentState.STA);
thread.IsBackground=true;
Start(新元组(Dispatcher.CurrentDispatcher,someObject));
}
因此,我在语句“this.tmp=0”上加了一个分隔符,当我关闭MFC应用程序时,它不会被击中。假设调度程序没有被关闭,但线程被中止,这样安全吗

如果线程中止,会产生什么后果

更新:

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

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


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

如果您不关闭dispatcher,线程将卡在消息循环中,并且不会退出主线程,您可以执行以下操作

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

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

在后台线程的
return
语句上设置一个断点,看看它是否被命中。允许MFC应用程序的主线程终止而不显式等待工作线程完成将始终终止整个进程。谢谢Hans先生。这使我在MFC即将退出时正确地调用调度程序上的shutdown。但是,我仍然很好奇,如果调度器没有显式关闭,会产生什么后果。这是真的,尤其是关于我发布的示例代码,但我更担心的是不太明显的副作用。在我遇到的问题中,我没有调用Dispatcher.Run(),并且在线程执行期间(不是很明显)有一段时间Dispatcher对象分配了资源。不在该线程的调度程序上调用shutdown导致调度程序对象挂起资源,并且从不进行垃圾收集。我仍然有点好奇,当线程被简单中止(而不在调度程序上调用shutdown)时,分配的资源会发生什么情况。现在,我运行的假设是CLR会处理它,并且有一条规则总是在后台线程上创建的调度程序上调用shutdown。当您关闭应用程序时,所有后台线程都将被终止,并且具有调度程序的线程也将被终止。如果不调用Dispatcher.Run(),另一个对象可以调用Dispatcher.CurrentDispatcher,如果当前线程没有Dispatcher,则该对象将强制创建Dispatcher。至于中止线程,我认为当线程被中止时,线程堆栈被破坏,GC可以收集所有对象,但不一定释放所有资源。