0

我正在为 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 的机制?

提前致谢。

4

1 回答 1

0

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

在这种情况下,这意味着让您的包装器完全了解并控制哪些线程接触 MySQL、这些线程何时启动以及何时停止。

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

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

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

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

于 2010-03-15T04:53:24.560 回答