在退出之前跟踪 - 并正确结束 - C# - C++/CLI - C++ Windows 窗体应用程序中的本机和托管线程

Posted

技术标签:

【中文标题】在退出之前跟踪 - 并正确结束 - C# - C++/CLI - C++ Windows 窗体应用程序中的本机和托管线程【英文标题】:Tracking - and correctly ending - native and managed threads in a C# - C++/CLI - C++ Windows forms application prior to exit 【发布时间】:2010-07-20 10:44:20 【问题描述】:

这是来自:

Debugging a Multithreaded C# - C++/CLI - C++ Solution in Visual Studio 2008: What are these threads?

请原谅格式,我只是在这里重复了一些应用程序的描述:

我继承了一个由三个级别的代码组成的项目。最低层是与硬件交互的本机 C++。这是成熟、稳定且经过良好测试的。中间级代码是 C++/CLI,它与包含 UI 元素和一些附加功能的*** C# 代码交互。这段 C# 代码不完整,并且在开发中匆忙:它经常崩溃并且不适合目的。我的任务是调试它并完成它。

我从我提出的最后一个问题中收到了一些非常有用的信息 - 但现在还有更多问题!我现在的问题是,当我调用 Application.Exit() 来关闭 UI 并退出应用程序时,会抛出异常:

System.InvalidOperationException: Collection was modified; enumeration operation may not execute

我了解这是因为我需要确保在调用 Application.Exit()(或 Application.ExitThread())之前我的所有线程都已结束。在我进一步调查时,我尝试使用 MainForm.Close() 作为快速修复,但它并没有缓解问题。

我不想只调用 Thread.CurrentThread.Abort(),主要是因为一些线程源自代码的 C++ 部分,通过 Boost::Thread,我不确定我到底可以使用哪些资源处于不受欢迎的状态(许多代码由用于与硬件交互的对象组成,例如串行端口 - 它不是通过 RAII 实现的,所以我对暴力破解相当谨慎)。

我希望能够做的是确定哪些线程正在做什么,并在退出应用程序之前优雅地结束它们。然而,在 VS 2008 中,堆栈跟踪 - 激活了“显示外部代码” - 仅显示

[Native to managed transition]
[Managed to native transition]

所以我仍然难以追踪各个本机线程,从而找出结束它们的最佳方法。

我尝试使用 Allinea DDTLite,它看起来很棒 - 但我的 VS 安装出现了一些问题,我不得不禁用插件,所以这不是一个解决方案。

总结一下:确保所有线程(包括托管线程和本机线程)正确完成的最有效方法是什么,以便 UI 和 整个应用程序可以干净地退出吗?

【问题讨论】:

您需要几个选项来完成此操作:“显示外部代码”只是其中之一。您还必须取消选择“仅我的代码”并使用“混合”调试器(最后一个是项目选项,默认为“自动”)。 谢谢本,很高兴知道! 【参考方案1】:

我希望能够做的是确定哪些线程正在做什么

您无法完成这项工作。有一些方法可以枚举进程中的线程,例如托管的 Process.Threads 属性或本机 Thread32First/Next,但是您没有获得关于线程的足够信息来了解它们的作用。并且最肯定不会干净地关闭它们。 .NET 框架为了自己的目的使用线程(例如调试器线程和终结器线程以及少量线程池线程)使情况更加复杂。

您可以使用 TerminateThread 粗鲁地终止这些线程,尽管终止终结器线程会立即使程序崩溃,但这与使用 Environment.Exit() 粗鲁地终止进程没有什么不同。需要注意的是,没有什么可以很好地清理。不过,Windows 会清理大部分弹片。

这通常不是问题。你知道你启动了哪些线程,还应该有一种机制要求它们关闭。这通常通过发出事件信号来完成,该事件在线程的主循环中进行了测试。等待线程句柄确认线程确实退出了。之后您可以关闭窗口。

但这可能是缺少的管道,您必须添加它。如果当前的本机 C++ 代码没有处理线程关闭的机制,那么您将遇到一个相当大的问题。我猜想维护这个原生 C++ 代码才是真正的问题。您可能需要雇一把枪才能完成这项工作。

【讨论】:

谢谢汉斯,这实际上很有帮助。我想知道这将是一个多大的问题,或者我是否完全错了。好消息是我的 C++ 经验多于 C# 经验,所以我将从本机代码开始并逐步提高 :-)

以上是关于在退出之前跟踪 - 并正确结束 - C# - C++/CLI - C++ Windows 窗体应用程序中的本机和托管线程的主要内容,如果未能解决你的问题,请参考以下文章

如何将 MouseListener 留在 ChildComponent 上但正确跟踪鼠标在父级上的进入和退出?

C# winform 点击一个按钮退出窗体 并关闭相应的进程

进程以退出代码 -1073741819 (0xC0000005) 结束 - C,CLion 但输出没有任何问题

Python - 正确杀死/退出期货线程?

如何在c#中跟踪windows事件

如何正确停止线程