在一个线程中:
void CMainFrame::OnPlay()
{
       ...
    g_bThreadStop = false;// 线程运行标记
    DWORD dwThreadID;
    m_hThread = CreateThread(NULL,0,FLSTrainThread,NULL,0,&dwThreadID);
       ...
}void CMainFrame::OnStop() 
{
    g_bThreadStop=true;  // 设置停止标记
    DWORD dwRet=WaitForSingleObject(m_hThread,1000*5); //等待5秒
    if(dwRet==WAIT_OBJECT_0)// 线程成功结束
    {
        ...
    }
    if(dwRet==WAIT_TIMEOUT)  //超时
    {
       // MessageBox("非正常结束线程!");  ------(1)
        TerminateThread(m_hThread,-1);
    }
}DWORD WINAPI FLSTrainThread(LPVOID lpParameter) 
{
    while(!g_bThreadStop)
    {
        ...
    }
    AfxMessageBox("成功结束线程!");
    return 0;
}
问题1:当执行OnStop的时候,g_bThreadStop已经置为false了,为什么FLSTrainThread并没有
执行AfxMessageBox("成功结束线程!"),而是进入if(dwRet==WAIT_TIMEOUT)内部?如果在加入(1)的代码,那么会先后执行MessageBox("非正常结束线程!");
AfxMessageBox("成功结束线程!");      真是奇怪!
问题2:我想在CreateThread,调用FLSTrainThread的时候,想向FLSTrainThread传入一个整数
参数,我如下的做法为什么不可以?该怎么做?
int Index=100;
CreateThread(NULL,0,FLSTrainThread,&Index,0,&dwThreadID);
然后在
DWORD WINAPI FLSTrainThread(LPVOID lpParameter) 
{
    int index = *lpParameter;  //为什么不可以?
    ...
}

解决方案 »

  1.   

    另一贴也是100分:
    http://expert.csdn.net/Expert/topic/1738/1738628.xml?temp=.9618647
      

  2.   

    1:
    试试这么定义g_bThreadStop:
    volatile bool g_bThreadStop;
      

  3.   

    问题1:
    可能你的现成的循环,每一步都需要比较长的时间,造成你的等待函数等不及了。问题2:
    局部变量作用域的问题,那个局部变量已经不存在了,你不能通过传地址的方法。如果你只传递一个整数,那你应该采用传值的方法。============================================================================
    提问题时标题要简明扼要地说明问题内容,切忌使用"急","求救"之类不能说明问题的标题
    http://alphasun.betajin.com/                            给我发信息请附带原帖地址
    http://www.betajin.com/alphasun/index.htm
    DocWizard C++程序文档自动生成工具 | Wave OpenGL | HttpProxy | AjaxParser词法分析
      

  4.   

    问题1:
        当执行OnStop的时候,g_bThreadStop已经置为true了,
        为什么FLSTrainThread并没有执行AfxMessageBox("成功结束线程!"),
        而是进入if(dwRet==WAIT_TIMEOUT)内部?
        
        答:因为线程现在没有结束,原因是全局的停止标记g_bThreadStop没有传递过去.
    线程内部的那个g_bThreadStop只是真正的g_bThreadStop的一个拷贝,只有当线程正常结束时
    才会改变成指定标志.解决该问题有两种方法1是用事件来同步,2是将g_bThreadStop声明为volatile 即可;
           如果在加入(1)的代码,那么会先后执行MessageBox("非正常结束线程!");
        AfxMessageBox("成功结束线程!");      真是奇怪!
       答:由于前面的原因,线程没有结束因而在指定的时间内不会成功返回(事实上线程还在正常运行),因而无秒之后,会返回超时标志.进而执行MessageBox("非正常结束线程!");,又因为你
    TerminateThread了一把,强制线程退出,所以线程会执行到AfxMessageBox("成功结束线程!");
    //====================================================================
    问题2:
     我想在CreateThread,调用FLSTrainThread的时候 想向FLSTrainThread传入一个整数
     参数,我如下的做法为什么不可以?该怎么做?
    int Index=100;
    CreateThread(NULL,0,FLSTrainThread,&Index,0,&dwThreadID);
    然后在
    DWORD WINAPI FLSTrainThread(LPVOID lpParameter) 
    {
        int index = *lpParameter;  //为什么不可以?
        ...
    }   答:原因是int Index=100;是个局部变量,且它是自动类型的变量,
    也就是说没有固定的地址,因而解决这个问题的方法也有两个1是将Index声明为静态变量
    2.是将Index变成类的成员变量,然后对其使用指针或引用.
      

  5.   

    to:everandforever(Forever) , yamei2000(临风) :
    (1)我已经按照你们的意思定义:volatile bool g_bThreadStop; 但是问题还是没有解决;(2)关于这个问题:我在程序里加入:MessageBox("非正常结束线程!");  
    则会执行 AfxMessageBox("成功结束线程!");
    不加入就不执行AfxMessageBox("成功结束线程!");-----奇怪!
      

  6.   

    (2)不加MessageBox("非正常结束线程!");  时主线程结束后,FLSTrainThread也结束了,是非正常结束。而加入MessageBox("非正常结束线程!");  后,这个语句的执行,使得主线程结束比FLSTrainThread结束的晚。
      

  7.   

    用CEvent SetEvent()进行同步
      

  8.   

    不太懂,也来凑热闹
    会不会是AfxMessageBox的问题,这样试试:
    DWORD WINAPI FLSTrainThread(LPVOID lpParameter) 
    {
        while(!g_bThreadStop)
        {
            ...
        }
        //AfxMessageBox("成功结束线程!");把它放到if(dwRet==WAIT_OBJECT_0)里去
        return 0;
    }
      

  9.   

    我认为是
    DWORD dwRet=WaitForSingleObject(m_hThread,1000*5); //等待5秒
    等待时间太短,而你的线程处理函数中的循环体执行时间大于5秒,改为
    DWORD dwRet=WaitForSingleObject(m_hThread,INFINITE); 试一试在加入(1)的代码时,当执行完
    // MessageBox("非正常结束线程!");  ------(1)之后,循环体由于g_bThreadStop=true退出,接着执行AfxMessageBox("成功结束线程!");不知道对不对,我不大懂多线程
      

  10.   

    关于问题一:
    DWORD dwRet=WaitForSingleObject(m_hThread,1000*5);换成
    DWORD dwRet=WaitForSingleObject(m_hThread,INFINITE);以后,程序就进入了死等待状态,似乎g_bThreadStop对于停止线程FLSTrainThread(LPVOID lpParameter)没有起作用!另外:MessageBox("非正常结束线程!");  ------(1)处替换成
    int j=0;
    for(int i=0;i<10000;i++)
       j++;
    效果就不一样;前者会让子线程FLSTrainThread执行AfxMessageBox("成功结束线程!");
    而后者就不能,奇怪...关于问题二:
    问题已经解决。
      

  11.   

    补充:关于全局变量g_bThreadStop我申明如下:
    BOOL volatile bThreadStop;
      

  12.   

    为了能说明问题,子线程我以修改如下,问题依旧...
    BOOL volatile bThreadStop; //全局变量
    DWORD WINAPI FLSTrainThread(LPVOID lpParameter)  
    {
        while(!g_bThreadStop) 
        {
     //空
        }
        AfxMessageBox("子线程结束!");
        return 0;
    }// bThreadStop似乎没有受OnStop() 中 bThreadStop=true的影响...
      

  13.   

    你干脆把工程email给我,不到5分钟我就可以搞定。
    [email protected]。记得用“紧急邮件”,这样速度快
      

  14.   

    这里是不是有一个操作系统调用中的时间片轮转的问题。使用 
    MessageBox("非正常结束线程!")这句代码时,用时比较少的,这时还是
    onstop函数在占用cpu,它会调用TerminateThread来终止线程,线程被
    终止,当然就不会执行执行AfxMessageBox("成功结束线程!")啦。使用循
    环体时,时间较长,可以保证onstop在执行TerminateThread之前时间片用
    完,线程函数取得cpu的控制权就会执行AfxMessageBox("成功结束线程!")
    啦。
    对于第一个问题,也可以通过上面的操作系统的时间片轮转调度来解释。
    多线程的问题和操作系统的调度很有关系。对于这个问题,可以把线程的
    优先级设置的低一点,这样你加不加MessageBox("非正常结束线程!")结果
    都不会改变的:只输出“非正常结束线程“。
      

  15.   

    AfxMessageBox("子线程结束!");有问题我试了一下,TRACE("子线程结束!");就正常。研究中
      

  16.   

    ::MessageBox(NULL, "STOP","成功结束线程!",MB_OK);
    换成这个就ok了。是不是AfxMessageBox要主线程来调用的?
      

  17.   

    to:chenlilei
    关键是:我执行OnStop()
    先执行 bThreadStop = true;然后
    dwRet=WaitForSingleObject(m_hThread,INFINITE); //程序进入死等待...
    为什么bThreadStop 这个标记没有被子线程FLSTrainThread中
    while(!FLSTrainThread)
    {
       //
    }
    识别呢?
    按照理解,子线程应该跳出循环才对啊。
      

  18.   

    看一下AfxMessageBox的源码就知道了
    int AFXAPI AfxMessageBox(LPCTSTR lpszText, UINT nType, UINT nIDHelp)
    {
    CWinApp* pApp = AfxGetApp();
    if (pApp != NULL)
    return pApp->DoMessageBox(lpszText, nType, nIDHelp);
    else
    return pApp->CWinApp::DoMessageBox(lpszText, nType, nIDHelp);
    }
    并不是bThreadStop 这个标记没有起作用,而是子线程调用AfxMessageBox之后程序陷入了死等状态。所以,换成::MessageBox(NULL, "STOP","成功结束线程!",MB_OK);
    就可以了
      

  19.   

    hwonzor(闲人) :
    看了你上面的原码,不清楚为什么AfxMessageBox会陷入死等状态状态,能解释一下吗?
      

  20.   

    按照闲人的做法去掉AfxMessageBox,主线程可以正常结束。不过,还是不理解why...
    另对于下面的代码:m_hThread = CreateThread(NULL,0,FLSTrainThread,NULL,0,&dwThreadID);
       ...
    SuspendThread(m_hThread); //    ---------(1)
    ResumeThread(m_hThread);  //    ---------(2)bThreadStop = true;
    dwRet=WaitForSingleObject(m_hThread,INFINITE); 如果程序只加入(1)程序陷入死等待
    如果程序加入(1)、(2)程序正常结束主线程,是不是WaitForSingleObject
    无法取到处于取到挂起状态的m_hThread?有什么变通的方法?
      

  21.   

    闲人 说的没错,你的AfxMessageBox("子线程调用结束!")造成了你所不期望的等待。
    于是就造成了主线程等不及。
    另外,我在你的工程里面加了一些TRACE语句,你将可以清楚的看到你的现成执行的流程。
      

  22.   

    由于各位的热心帮助,问题已经解决了。遗留的问题:
    (1)
    正如hwonzor(闲人) 、alphapaopao(炮炮) 所指出来的,由于AfxMessageBox("子线程调用结束!")造成了所不期望的等待,于是就造成了主线程等不及。但是我并不是很理解为什么会这样(看了闲人提供的AfxMessageBox原码后还是不解)?能帮我解释一下吗?可以在以后避免类似的问题...(2)如题不修改AfxMessageBox这行;
    我发现Stop主线程中:MessageBox("非正常结束线程!");  ------(1)
    有了上面这个行代码,它会“激发”子线程中AfxMessageBox("成功结束线程!");
    没有那话,哪怕执行10000行代码,也不会执行AfxMessageBox;
    =========
    尽管如论等多少时间,都是进入if(dwRet==WAIT_TIMEOUT)  //超时
    程序体中。