做了一个mfc多线程程序,
先定义两个变量:
volatile BOOL m_running;
volatile bool m_multiThreadend;//多线程是否结束在主线程里调用:
m_running=true;
        m_CThread=AfxBeginThread((AFX_THREADPROC)downloadData,this,0,0,0);void WINAPI downloadData(LPVOID lpvoid)
{
    while(m_running)
    {
        /*这里是业务逻辑的代码,关键代码10几行,加了9条打印执行时间的代码
          struct _timeb timebuffer;
          _ftime(&timebuffer);
  FILE *pf = fopen("log.txt","a");
  CString s;
  s.Format("1:  %ld  %u\n",timebuffer.time,timebuffer.millitm);
  fwrite(s,sizeof(char),s.GetLength(),pf);
          fclose(pf);
          打印出当前时间的UTC时间,即1970年1月1号午夜到现在的秒数和当前毫秒数。格式类似:
          1:  1303000981  443
          2:  1303000981  443
          3:  1303000981  443
          4:  1303000981  443
          5:  1303000981  443
          6:  1303000981  474
          7:  1303000981  526
          8:  1303000981  527
          9:  1303000981  587
          */
      Sleep(60);//60毫秒执行一次。 
      }
      m_multiThreadend=true;//多线程结束掉了。
      //这里向log.txt中写入:m_running is false,thread is to be end.
      AfxEndThread(0,true);
}void CTestDlg::OnButtonClick()
{
     m_running=false;//m_running置为false,上面函数的while循环不满足,就会退出多线程。
     //在这里向log.txt中写入:set m_running to false
     Sleep(1);//听说sleep可以让当前线程让出cpu,所以加了这句话
     bool b=SwitchToThread();//这句按理说也可以切换线程。
     //这里将b打印到log.txt中
     int i;
     while(m_multiThreadend==false&&i<20)//等待2秒让多线程结束
{
Sleep(100);
i++;
}
     if(i==20)//2秒全过去了
     {     
          MessageBox("timeout");
          //我在这里还加入了往log.txt写记录的语句,输出的格式为201303000983  614 timeout ===================
     }else
          MessageBox("OK");
}
程序大体就这样,运行程序有时没问题,一切按预计的,多线程被结束掉。可是也有时会出现等待超时的现象。
这时的log.txt打印消息为:
1303000981  612  set m_running to false
==============0=============//这是打印出的b的值,switchtothread返回false
1303000983  614 timeout ===================//OnButtonClick中等待超时了
1:  1303000981  587
2:  1303000981  587
3:  1303000981  587
4:  1303000981  587
5:  1303000981  587//这里和下一句间隔了两秒,看来这个线程在这两秒没有等到CPU时间片。
6:  1303000983  635
7:  1303000983  685
8:  1303000983  685
9:  1303000983  745
17 0:43:3:745 m_running is false,thread is to be end.
由上可以看出,SwitchToThread返回false,可是根据后面的打印消息看出,另一个线程还在运行着呢,为什么切换失败。还有,Sleep不是会让当前线程让出CPU时间吗。为什么有时这段程序正常,有时就结束不掉多线程呢。

解决方案 »

  1.   

    void WINAPI downloadData(LPVOID lpvoid)
    改成
    unsigned int __cdecl downloadData(LPVOID Parameter)
      

  2.   

    pfnThreadProc
    UINT __cdecl MyControllingFunction( LPVOID pParam );UINT __cdecl downloadData(LPVOID pParam);
      

  3.   

    改了,还是这样:
    1303008172  714  set m_bRun to false
    ==============0=============
    1303008174  716 timeout ===================
    1:  1303008172  630
    2:  1303008172  630
    3:  1303008172  630
    4:  1303008172  630
    5:  1303008172  630
    6:  1303008174  734
    7:  1303008174  788
    8:  1303008174  789
    9:  1303008174  849
      

  4.   

    等待超时后,OnButtonClick返回,那个线程在执行一次while循环就结束掉了。
      

  5.   

    这样不就行了,你可以使用WaitForSingleObject来等待线程结束
      

  6.   

    其实我一开始就是用WaitForSingleObject做的,我代码里有WaitForSingleObject代码片段,
    DWORD result = WaitForSingleObject(hMutex,100);//第二个参数本来写的是INFINITE,可是会出现程序卡死的现象,换成一个具体的数就会出现timeout的现象。
    if(result == WAIT_TIMEOUT)
    {
    // MessageBox("Timeout");
    FILE *pFile = fopen("log.txt","a"); GetSystemTime(&t1);
    CString str;
    str.Format("%d %u:%u:%u:%u Timeout while waitforsingleobject \n",
    t1.wDay,t1.wHour,t1.wMinute,t1.wSecond,t1.wMilliseconds);
    if(f!=NULL)
    fwrite(str,sizeof(char),str.GetLength(),pFile);
    fclose(pFile);
    // BOOL b=TerminateThread(m_CEvfThread->m_hThread,0);
    }
    另外在另一个线程:
    while(m_runing)
    {
       DWORD result = WaitForSingleObject(hMutex,100);//while循环体第一句话
       .....
       ReleaseMutex(hMutex);
       Sleep(60);
    }
      

  7.   

    谁先拥有hMutex,另一个就等它。等到先拥有hMutex的线程执行到ReleaseMutex()就获得了hMutex.
      

  8.   

    把你的代码发到[email protected]给我看看
      

  9.   

    我后来将程序改成单线程了。其实我一开始就陷入误区,这个程序实现在对话框上实时显示图像,我开始用的是Sleep(60),这样会是对话框卡住,其实画图功能占用时间不多,可以不用多线程。使用timer计数器SetTimer(1,60,0)就可以了。
      

  10.   

    我后来有看了一些多线程死锁的文章,觉得这个程序多线程无法切换其实是死锁了,我在新开的线程中执行了画图操作,用到了对话框的一些控件变量,这便会产生消息,windows将消息发送到主线程,这是主线程正在执行Sleep,两个线程都挂起了。参考了文章http://blogold.chinaunix.net/u2/75914/showart_2241144.html上的思路,加上
    MSG msg;
    DWORD drect = ::MsgWaitForMultipleObjects(1,&m_CThread->m_hThread,false,1000,QS_ALLINPUT);
    if(drect == WAIT_OBJECT_0+1)
    {
    while(PeekMessage(&msg,NULL,0,0,PM_REMOVE))
    {
    TranslateMessage(&msg);
    DispatchMessage(&msg);
    }
    }
    else
    {
    MessageBox("wait for multipleobject failed");
    }
    简单的测试了一下,貌似好了。