两个线程可以调用同一个DLL中的两个函数吗?

Posted

技术标签:

【中文标题】两个线程可以调用同一个DLL中的两个函数吗?【英文标题】:Can two functions in same DLL be called by two threads? 【发布时间】:2014-08-27 22:57:23 【问题描述】:

我用Visual C++ 2008写了一个DLL MyDLL.dll,如下:

(1) MFC 静态链接 (2) 使用多线程运行库。

在DLL中,这是两个导出函数共享的全局数据m_Data,如下:

    ULONGLONG WINAPI MyFun1(LPVOID *lpCallbackFun1)
    
        ...
        Write m_Data(using Critical section to protect)
        …

        return  xxx;
    

    ULONGLONG WINAPI MyFun2(LPVOID *lpCallbackFun2)
    
        ...
        Suspend MyThread1 to prevent conflict.
        Read m_Data(using Critical section to protect)
        Resume MyThread1.
        …

        return  xxx;
    

在我的主应用程序中,它会先调用LoadLibrary来加载MyDLL.dll,然后获取MyFun1和MyFun2的地址,然后做如下事情:

(1) 启动一个新线程MyThread1,它会调用MyFun1来做一个耗时的任务。 (2) 启动一个新线程MyThread2,会多次调用MyFun2,如下:

    for (nIndex = 0; nIndex = 20; nIndex)
    
    nResult2 = MyFun2(lpCallbackFun2);
    NextStatement2; 
    

虽然 MyThread1 和 MyThread2 使用临界区来保护共享数据 m_Data,但我仍然会在访问共享数据之前暂停 MyThread1,以防止任何可能的冲突。

问题是:

(1) MyFun2第一次调用时,一切正常,MyFun2(即nResult2)的返回值为1,符合预期。 (2) MyFun2第二、三、四次invoke时,MyFun2中的操作执行成功,但MyFun2(即nResult2)的返回值是随机值,而不是期望值1。我尝试使用Debug来跟踪到 MyFun2,并确认最后一个 return 语句只是返回一个值 1,但是调用者在检查 nResult2 时将收到一个随机值而不是 1。 (3) MyFun2 第四次调用后返回 MyFun2 后面的下一条语句,无论下一条语句是什么,我总是会得到“buffer overrun detected”的错误。

我认为这看起来像是堆栈损坏,因此请尝试进行一些测试:

    我确认编译器中的 /GS(堆栈安全检查)功能已开启。 如果在 MyThread1 中的 MyFun1 完成后调用 MyFun2,则一切正常。 在调试模式下,MyFun2 中读取共享数据 m_Data 的代码行不会导致任何错误或异常。 MyFun1 中写入共享数据的代码行也不会。

那么,如何解决这个问题

谢谢!

【问题讨论】:

我不知道您的问题,可能是您未显示的大型代码中的一个无关问题。但是请不要暂停其他线程,那将导致灾难! 临界区将在需要时停止和恢复线程,前提是它们被正确使用。 你使用SuspendThread()函数吗? 问题解决了,我获取到函数地址后,缺少WINAPI修饰符。 【参考方案1】:

我想在这一行

Suspend MyThread1 to prevent conflict.

您正在使用SuspendThread() 函数。这就是它的文档所说的:

这个函数主要是为调试器设计的。 它不适用于线程同步。如果调用线程尝试获取挂起线程拥有的同步对象,则在拥有同步对象(例如互斥锁或临界区)的线程上调用 SuspendThread 可能会导致死锁。为避免这种情况,应用程序中不是调试器的线程应向其他线程发出信号以暂停自身。目标线程必须设计为监视此信号并做出适当的响应。

所以,简而言之:不要使用它。关键部分和其他同步对象可以正常工作。

【讨论】:

【参考方案2】:

永远不要使用 SupsendThread!!!绝不! SuspendThread 仅用于调试目的。

原因很简单。你不知道你在哪里暂停线程。当线程阻塞您要使用的资源时,它可能是及时的。还有一堆 CRT 函数使用线程同步。 只需使用关键的 sectins 或 mutexes。

只需在此处查看简单示例:http://blog.kalmbachnet.de/?postid=6 和此处 http://blog.kalmbachnet.de/?postid=16

【讨论】:

【参考方案3】:

由于这是一个 windows 程序,您可以在读取或写入共享数据时使用基于 windows 的互斥锁或信号量和 WaitForSingleObject。

【讨论】:

以上是关于两个线程可以调用同一个DLL中的两个函数吗?的主要内容,如果未能解决你的问题,请参考以下文章

可以在多线程 DLL 的接口函数中创建线程吗?

同时运行两个线程

C#调用C/C++的dll,一个库中包括多个函数,每调用一个函数都要用DllImport加载吗?求大神

Qt调用dll中的功能函数

python调用dll怎么传入一个指针接收结果?

静态库 动态库 调用