问个VC的问题,多线程情况下,主线程在onclose()函数退出时,需要确认各个子线程完成了某件事情,于是我用一个while+sleep的代码来查询各个子线程对应的一组全局变量,看是否已经被子线程置1,全部置1主线程才返回,子线程也是while+sleep结构的,结果发现主线程在Sleep(50)处循环,子线程根本跑不到if处,导致软件退不出来。源码如下,请大侠指点:BOOL bExitThread[20];
HANDLE devHandle[20];
void CABCDlg::OnClose() 
{
for (int i=0;i<20;i++)
  {
  bExitThread[i] = TRUE;
  }
for(int i=0;i<20;i++)
{
while(devHandle[i] != NULL)
Sleep(50); }
CDialog::OnClose();
}UINT CAXToolDlg::TesterThreadFunc(LPVOID lparam)
{
while(1)
{
myfunc(devHandle);
Sleep(500);
if(bExitThread[lparam] == TRUE) //主线程发出了退出线程命令
{
::CloseHandle(devHandle[lparam]);
devHandle[lparam] = NULL;
return FALSE;
}
}
}子线程主线程

解决方案 »

  1.   

    看看是不是在myfunc里死循环了
      

  2.   

    WatitForSingleObject 等待线程退出
      

  3.   

    for(int i=0;i<20;i++)
     {
     while(devHandle[i] != NULL)
     Sleep(50);
     
    }
    上面的语句就是死循环的,我猜测你的意思应该改为:
    while(1)
    {
        int i=0;
       for(i=0;i<20;i++)
       {
           if(devHandle[i] != NULL)
               break;
       }
       if(i>=20)
           break;
       else
           Sleep(50);
       }
    }
      

  4.   

    我的意思是OnClose()里面,20个子线程必须全部将devHandle设置为NULL之后才能才能退出for,这样才能安全退出程序,否则任意一个子线程没有安全关闭devHandle,都有可能导致硬件(USB设备)跑死。因此,我最开始写的代码是没错的。
      

  5.   

    主线程一直在Sleep处,子线程无论在哪里打断点都跑不到,WatitForSingleObject这个我也试过了,跟用全局变量是一样的效果。
      

  6.   


    //程序退出保证所有子线程结束
    static HANDLE s_ListenHandle;
    //引用计数,默认是0
    static int s_ListenCount = 0;
    static CRITICAL_SECTION s_csListen;void ResetUserHandle()
    {
    EnterCriticalSection(&s_csListen);
    if(s_ListenCount == 0)
    {
    ResetEvent(s_ListenHandle);
    }
    ++s_ListenCount; //引用计数加1
    LeaveCriticalSection(&s_csListen);
    }void SetUserHandle()
    {
    EnterCriticalSection(&s_csListen);
    --s_ListenCount;//引用计数减1
    if (s_ListenCount == 0)
    {
    SetEvent(s_ListenHandle);
    }
    LeaveCriticalSection(&s_csListen);
    }//线程函数的开始处调用ResetUserHandle(), 线程函数退出的地方调用SetUserHandle()//onclose里面这样调用:
    DWORD ret = WaitForSingleObject(s_ListenHandle, 20000);//等待所有的子线程退出
    if (ret == WAIT_TIMEOUT)
    {
    CDebug::Log("等待了20秒, 还有子线程没有退出");
    }
    else if (ret == WAIT_OBJECT_0)
    {
    CDebug::Log("所有子线程都退出了");
    }
    刚好我之前做的一个项目里面就有这个问题, 使用事件+引用计数来处理
      

  7.   

    LZ的代码在单CPU,单核,无超线程情况下,主线程的while+sleep是有可能让出CPU的啊,不知道为什么子线程得不到执行(如果是忙等待才会如此)。
    试下这样
    1.主线程设置退出标志
    2.主线程等待子线程退出WaitForMultiObjects
    3.大家都退出了
      

  8.   

    多谢“吉拔猫”的热心回复,但测试了还是不管用啊,最后ret返回值是-1,我看了下宏定义是WAIT_FAILED。
    看来问题是出在子线程上面,因为发现主线程通过全局变量bExitThread[i] = TRUE;告诉子需要退出时,子线程并没有退出;
      

  9.   

    http://download.csdn.net/detail/robertbaker/5125457
      

  10.   

    但看这2段代码没发现什么问题啊。检查下其它地方呢? 比如初始化 devHandle[20] 保证都为NULL,
     new 一个 devHandle 必须马上为相应的创建个线程(LPVOID lparam)线程参数要正确。
      

  11.   

    多谢各位的关注,问题我自己找到了:OnClose是一个消息函数,而我在myfunc(devHandle)函数中给主窗口用SendMessage()发送的一些消息,这样就冲突了,后来换成PostMessage替换后就解决。