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

时间:2014-08-27 22:57:24

标签: c++ multithreading dll mfc

我用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的第二次,第三次和第四次调用时,MyFun2中的操作成功执行,但MyFun2的返回值(即nResult2)是一个随机值而不是期望值1.我尝试使用Debug来跟踪到MyFun2,并确认最后一个return语句只返回值1,但是在检查nResult2时,调用者将收到一个随机值而不是1。 (3)在第四次调用MyFun2并返回到MyFun2的下一个语句之后,无论下一个语句是什么,我都会遇到“检测到缓冲区溢出”错误。

我认为这看起来像堆栈损坏,所以尝试进行一些测试:

  1. 我确认编译器中的/ GS(堆栈安全检查)功能已启用。
  2. 如果在MyThread1中的MyFun1完成后调用了MyFun2,那么一切都会正常。
  3. 在调试模式下,MyFun2中读取共享数据m_Data的代码行不会导致任何错误或异常。 MyFun1中的代码行也不会写入共享数据。
  4. 那么,如何解决这个问题

    谢谢!

3 个答案:

答案 0 :(得分:1)

我想在这一行

Suspend MyThread1 to prevent conflict.

您正在使用SuspendThread()功能。这就是它的文档所说的内容:

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

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

答案 1 :(得分:1)

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

原因很简单。你不知道你在哪里暂停线程。当线程阻塞您要使用的资源时,它可能正好赶上时间。还有一堆CRT函数使用线程同步。 只需使用危险的sectins或互斥体。

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

答案 2 :(得分:0)

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