我在dll里创建了一个线程,查资料知道不能在InitInstance()中创建,这个我弄好了,那么在主程序结束的时候,我怎么退出线程呢?比如说主程序点击右上的关闭按钮,我尝试在dll的ExitInstance()函数里设置一个Event,然后在线程中WaitForSingleObject(),然后在ExitInstance()中waitForSingleObject(myhThread,INFINITE) ,但是到waitForSingleObject(myhThread,INFINITE)程序始终在等待,估计是线程没有退出!!!相同的代码如果不用在dll中直接在一个exe中,是没有问题的!!!!这个问题困扰我好几天了,请各位高手指教,解决了马上给分,如果分不够另外开贴送分!!

解决方案 »

  1.   

    extern "C" int APIENTRY DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved)
    {
    UNREFERENCED_PARAMETER(lpReserved);
    if (dwReason == DLL_PROCESS_ATTACH)
    {
    //dll attach,初始化
    }
    else if (dwReason == DLL_PROCESS_DETACH)
    {
               //ll detach
               //可以试试让线程在这里退出
              }
    return 1;
    }
      

  2.   

    你的线程是怎么结束的?线程函数
    while(m_bThreadRun)
    {
      ....
    }结束的方法:
    m_bThreadRun = FALSE;
    waitForSingleObject(myhThread,INFINITE);但是线程一定要保证是一直在循环,能检测到 m_bThreadRun = FALSE
      

  3.   

    to:younggle(洋溢),是一直在循环,能检测到m_bThreadRun,我调试了一下,是在线程return 0的时候,跟进去是AfxEndThread()函数不动了,在往里是汇编,我看不懂,是__ExitThread()这里死锁不往下走了,不知到那位高人能来解说一下?
    to:aben456(相逢一笑)  我用向导生成的dll,已经看不到dllmain了,不过InitInstance和ExitInstance实际上调用的还是dllmain,问题依然
      

  4.   

    没有人能回答了吗?我又测了一下,如果在线程中
    while(bRun){
    .....
    return 0;
    }
    是可以退出的,如果是
    while(bRun){}
    return 0;// 在这里放断点是可以到的,但是在往下跑就死锁了!就不行了,所以怀疑是我设置bRun=FALSE的位置不对,我是在dll的ExitInstance里设置的,因为我只又在这里才知道主程序要退出啊!!!
      

  5.   

    看来你创建的是MFC形式的DLL,那么你可以就在ExitInstance里结束你创建的线程
    怎么结束,得取决于你的线程函数的写法
    1.如果你的线程函数是没有循环,但是用了等待变量,那么你应该调用SetEvent唤醒它,
    让线程自行结束就行
    2.如果你的线程函数是有while(bContinue)这样的循环,你又在ExitInstance里
    加入waitForSingleObject(myhThread,INFINITE)发现始终在等待,
    这是因为你bContinue还是为true,或者你在线程函数中也有waitForSingleObject(h1)
    这样的函数导致你的线程还在执行,那么你在ExitInstance里
    直接设置它 bContinue=false ,若有等待变量的话,你还应该SetEvent(h1)
    这样线程就自行结束了
      

  6.   

    to:linur(林曦)
    我的线程是这样的UINT MyFunc( LPVOID pParam )
    {
       while(bRun) // bRun是全局变量
        {
           if(::WaitForSingleObject(pParma->m_hEvent,10) == WAIT_OBJECT_0)
             {
                ......     // 我自己的操作
             }
        }
        return 0;     // 当在ExitInstance里设置bRun = false,函数在这里停住了,跟进去是
                      // AfxEndthread() 死锁了,实在是不明白问题原因
    }// 下面是ExitInstance的代码
    int CAlmMessApp::ExitInstance()
    {
       bRun = FALSE;
       ::WaitForSingleObject(p->m_hThread,INFINITE) // p = AfxBeginThread(DelayFunc,this);
    }现在的问题是如果退出的代码不在ExitInstance里,是没有问题的,如果是上面的样子,怎在
      

  7.   

    HANDLE *m_ExitThread;全局变量#define MaxWaitTimes 100  //线程每运转一次的间隔
    *****线程******
    for(;;)
    {
      DWORD dwRet=::WaitForSingleObject(m_ExitThread, MaxWaitTimes);
      if (dwRet!=WAIT_OBJECT_0) 
      {
        这里,你想干嘛就干嘛!
      }
      else
      {
        CloseHandle(m_ExitThread);
        return 0;
      }
    }*******结束线程*********
    Close()
    {
      if(m_ExitThread!=NULL)
         VERIFY(SetEvent(m_ExitThread));//设置线程退出  Sleep(MaxWaitTimes);//等待一个线程运转周期,确保线程退出
    }
      

  8.   

    bRun = FALSE;
    bRun是在哪里定义?
    又是在哪里修改的?
    修改成功了没有?
      

  9.   

    问题解决了,还是我自己解决的,郁闷~
    我发现不能在dll的exitInstance函数里waitforsingleobject(p->m_hThread),这样会死锁,
    其中, CWinthread *p = AfxBeginThead(Mythread,this);但是这样的用法在exe程序中是可以的,我现在折中的解决办法是另外设置一个Handle hquit,在thread退出时设置这个SetEvent(hquit),然后在
    dll里的ExitInstance(){ ::WaitForSingleObject(hquit,INFINITE);}虽然问题解决了,但是原理没弄懂,希望有懂得高手来给解释一下,为什么一样的代码在dll里会死锁,在exe程序里就可以用!!!
    btw:感觉在csdn里想问个答案真tmd难,在c++板块好点,你们说那么多星星都是怎么升上去的?
      

  10.   

    to qianyong325(帝王企鹅)
    你应该在主程序(就是应用程序对象类)的函数ExitInstance里(而不是DLL类那个ExitInstance)
    写上 
     bRun = FALSE; 
     ::WaitForSingleObject(hThread,INFINITE); 
    不用Wait函数也可以,你可以换为sleep(100);防止主线程退得太快而让辅助线程来不及正常退出 你原来的写法就会出来你说的问题,这是因为你虽然是创建在DLL中定义的线程,但是创建的线程
    还是在主程序空间,这样你退出时,主程序会强行销毁所有的资源,因此你不应该让DLL的ExitInstance去控件线程的退出
      

  11.   

    那为什么我改了退出方式以后,在dll的exitInstance里就可以退出了,实际上我不能修改exe里的代码,我只知道主程序在退出的时候会调用一次FreeLibrary,FreeLibrary的时候应该会调用dll里exitInstance(),这个函数,这个时候应该还没有销毁资源吧?如果都销毁了,那我更改退出方式应该也不能解决问题!!!欢迎继续讨论
      

  12.   

    你用另外设置一个Handle hquit,在thread退出时设置这个SetEvent(hquit),就和我上面说的
    在主线程里设置bRun = FALSE是一样的道理,你的方法也是让主线程去设置某个控制变量让线程退出.
    而不是把控制代码放到线程的ExitInstance()
      

  13.   

    结束线程:TerminateThread(hNetHandle[i],0);
    CloseHandle(hNetHandle[i]);
      

  14.   

    to: linur(林曦),你似乎没有明白我的解决办法。实际不是你说的而是
    UINT MyThread(void * pParam)
    {
       while(bRun)
        {
           ...
        }
      
      ::SetEvent(hquit);
      return 0;
    }dllApp::ExitInstance()
    {
      bRun = false;
      ::WaitForSingleObject(hquit,INFINITE);
      
      ...
    }to:tigerfox(风之力:=Doing.浪淘沙)
    我知道用TerminateThread()也可以结束线程,而且结束之后还应该delete thread;否则有泄漏,但是这种方法是mircosoft极力反对的,几乎所有的windows编程经典著作都说应该让线程自己结束,连afxEndThread这个函数都不推荐使用,作为一个星星,你就这样教导新人吗?
      

  15.   

    看不出是哪里出问题了~有点诡异,楼主是否中间有调用过CloseHandle?
      

  16.   

    to: qianyong325(帝王企鹅) 
    你把bRun = false; 放到dllApp::ExitInstance()里,注意仍然是主线程在执行这个函数。我已经在VC2003下写了测试过了,你这样做的结果虽然没有导致死锁,但是导致了主线程饿死现象,看看你写的代码
    dllApp::ExitInstance()
    {
      bRun = false;
      ::WaitForSingleObject(hquit,INFINITE);
      
      ...
    }
    当主线程执行到bRun=false;之前就释放掉了,其原因是当程序退出时,主线程会先执行ExitProcess释放掉你的辅助线程,从而让你的MyThread线程非正常退出,也就是直接从while循环中退出,从而MyThread不能正常执行::SetEvent(hquit);这句代码再次唤醒主线程,导致让主线程永久睡眠了(饿死了)
    不知道这样的解答你是否满意:)
      

  17.   

    to:linur(林曦)
    在主程序的exitInstance里调用了::FreeLibrary(),应该是在::FreeLibrary()里面调用的dllApp::ExitInstance()吧?你的意思是说在::FreeLibrary()之后就先退出辅助线程然后在调用dllApp::ExitInstance这个函数是吗?
    感谢你的解释,如果有什么可以继续说一下,晚上下班前就结贴了!分数都给你
      

  18.   

    我跟踪的结果显示主线程会先执行runtime函数ExitProcess来释放掉你的MyThread线程,并且释放掉其它资源,然后再调用dllApp::ExitInstance(),这个时候MyThread线程已经不存在了,所以主线程执行
    bRun = false;时没有起作用,从而执行下一句::WaitForSingleObject(hquit,INFINITE)就阻塞了
      

  19.   

    我如果另外设置一个handle来判断也就是说如果::WaitForSingleObject(hquit,INFINITE)中的hquit是在dll中另外创建的,而不是用pThread->m_hThread,那么我在调试的时候就可以跟踪到线程中::SetEvent(hquit);,在::WaitForSingleObject(hquit,INFINITE);就可以了,我想如果等待pThread->m_hThread就是你说的这种情况了,等下就结贴了,十分感谢你的帮助