C ++ / CLI托管线程清理

时间:2009-12-12 02:19:29

标签: c++-cli multithreading managed

我正在为MySQL嵌入式服务器编写托管C ++ / CLI库包装器。 mysql C库要求我为每个将要使用它的线程调用mysql_thread_init(),并为使用它后退出的每个线程调用mysql_thread_end()。

调试任何给定的VB.Net项目我至少可以看到七个线程;我想我的库只会看到一个线程,如果VB本身没有显式创建工作线程(对此有任何确认?)。但是,我需要客户端到我的库,以便能够在需要时创建工作线程,因此我的库必须在某种程度上具有线程感知。

我能想到的第一个选项是在我的类中公开一些“EnterThread()”和“LeaveThread()”方法,因此客户端代码将在开始时和退出DoWork()方法之前显式调用它们。如果(1).Net没有“神奇地”创建用户不知道的线程,并且(2)用户足够小心地在某种类型的try / finally结构中调用方法,这应该可行。

但是,我不喜欢让用户像这样手动处理事情,我想知道我是否可以帮她解决这个问题。在纯Win32 C / C ++ DLL中,我确实有DllMain DLL_THREAD_ATTACH和DLL_THREAD_DETACH伪事件,我可以根据需要使用它们来调用mysql_thread_init()和mysql_thread_end(),但在C ++ / CLI管理中似乎没有这样的东西码。以某些性能为代价(我认为不多)我可以使用TLS来检测“从新线程中使用”的情况,但我可以想象没有机制可以解决线程退出的情况。

所以,我的问题是:(1).net可以创建应用程序线程而用户不知道它们吗? (2)我可以使用类似于托管C ++ / CLI的DLL_THREAD_ATTACH / DLL_THREAD_DETACH的任何机制吗?

提前致谢。

1 个答案:

答案 0 :(得分:0)

基本问题似乎是您的库包装器无法充分了解与底层MySQL库正确通信所需的线程信息。在这种情况下,如果可能,我会尝试直接解决根问题。

在这种情况下,这意味着让你的包装器充分了解和控制哪些线程接触MySQL,当这些线程开始时以及何时停止。

因此,例如,包装器库中的顶级对象可以在内部启动并拥有一个线程池,池中的每个线程在启动时调用mysql_thread_init(),每个线程在关闭时调用mysql_thread_end()。这个线程池对于VB.net客户端代码是不可见的,但是在幕后,对包装器库的每个调用都会切换到用于数据库通信的线程池线程之一,然后将数据库响应传递回调用线程。

当客户端销毁包装器对象时,包装器对象会关闭并连接其内部线程池中的所有线程(在退出之前每个线程调用mysql_thread_end())。然后一切都被考虑在内。

这可能是不可能的,具体取决于您的情况的具体情况(每次打包到您的包装中都会产生上下文切换成本;请注意!),但我认为值得建议。

如果这样的事情对你不起作用,那么你要么按照你提到的方式调用某种魔法系统巫术(我不是一个CLI人或Windows人,所以我无法帮助你那里),或者你需要将责任传递给客户。执行后者的一种简单方法就是说“包装器对象只能在创建它的线程中使用”。当然,当你的客户不可避免地遵循这个限制时,你仍然会在那里面对一类新的可能的错误......