C++ cli C++/CLI管理的线程清理

C++ cli C++/CLI管理的线程清理,c++-cli,multithreading,managed,C++ Cli,Multithreading,Managed,我正在为MySQL嵌入式服务器编写托管C++/CLI库包装器。mysql C库要求我为将要使用它的每个线程调用mysql_thread_init(),并为使用它后退出的每个线程调用mysql_thread_end() 调试任何给定的VB.Net项目时,我至少可以看到七个线程;我想如果VB本身没有显式地创建工作线程,我的库将只看到一个线程(对此有任何确认吗?)。然而,我需要我的库的客户端能够创建工作线程(如果需要的话),所以我的库在某种程度上必须是线程感知的 我能想到的第一个选项是在我的类中公开一

我正在为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


提前感谢。

最基本的问题似乎是,您的库包装器对线程信息没有足够的可见性,无法与底层MySQL库正确通信。在这种情况下,如果可能,我会尝试直接修复根本问题

在这种情况下,这意味着让包装器完全了解和控制哪些线程接触MySQL,这些线程何时开始,何时停止

例如,包装器库中的顶级对象可以在内部启动并拥有一个线程池,池中的每个线程在启动时调用mysql\u thread\u init(),在关闭时调用mysql\u thread\u end()。这个线程池对于VB.net客户端代码来说是不可见的,但是在幕后,对包装器库的每次调用都会传递给一个线程池线程进行DB通信,然后线程池线程会将数据库响应传递回调用线程

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

这可能不可能,这取决于您的具体情况(每次调用包装器都会产生上下文切换成本;小心!),但我认为这是值得建议的


如果类似的东西对您不起作用,那么您需要按照您提到的思路调用某种魔法系统巫毒(我不是CLI人员或Windows人员,因此我无法在这方面帮助您),或者您需要将责任转交给客户机。实现后者的一个简单方法就是说“包装器对象只能在创建它的线程中使用”。当然,当客户端不可避免地无法遵循此约束时,您仍然会遇到一类新的可能的bug…

我可以看到还有[ThreadStatic]属性;也许,与TLS一样,如果句柄为nullptr,我可以分配一个从其构造函数调用init函数的对象,并且它会在处理时调用结束线程代码,但无法确定框架是否会从创建该对象的同一线程调用IDisposable代码。有人知道吗?嗨,谢谢,威尔。然而,整个想法是为了避免转换成本,因为不太可能有多个线程同时访问MySQL。公寓线程的性能受到了上下文切换的影响,这正是我想要避免的。无论如何,我现在迁移到SQLite,所以这一切都是学术性的。:)