zoukankan      html  css  js  c++  java
  • Never use AfxEndThread! 一个非常好的例子

    http://www.codeguru.com/forum/showthread.php?t=284440
    Hello,

    Thanks for the new forum.

    I thought I would put in a tip / warning that I have discovered and if anyone would like to comment on it, please do.

    Recently I developed a program that allowed the user to select a file, and then a worker thread would do some processing to it. It was very simple, because it was my first MFC application and I was doing it more for learning MFC than being able to use the actual program.

    While the worker thread processed the file, it periodically sent messages to a modal dialog box that had a progress control that reflected how much data had been processed by the worker thread. Also on the modal dialog box was a Cancel button that set a global variable to true that the worker thread checks at every iteration to see if it should end itself.

    Here is a very slimmed down version of my thread:

    Code:
    typedef struct tagTHREADPARMS{     CString pathname;} THREADPARMS;void CMyClass::SomeCallingFunction(){     THREADPARMS *ptp = new THREADPARMS;     ptp->pathname = m_pathname; // m_pathname is in our class      AfxBeginThread( ThreadFunc, (LPVOID) ptp );}DWORD ThreadFunc(LPVOID lpParam){    THREADPARMS *ptp = (THREADPARMS*) lpParam;    CString pathname = ptp->pathname;    delete ptp;    //open file with the pathname    while( !file.eof() )    {          if( g_bStopThread )          {                // send ''thread canceled" msg to modal dialog box                AfxEndThread( 0 );          }    }        // send "thread finished" msg to modal dialog box    AfxEndThread( 0 );}
    If the thread runs its course, AfxEndThread( 0 ) is called and it finishes completely without any user intervention. The thread exits fine and the program (in debug mode) exits fine with no memory leaks.

    However, if g_bStopThread is set to true, AfxEndThread( 0 ) is called, and the thread exits normally. However, when I close the program (when I am in debug mode) it shows a memory leak at a certain allocation number. When I use _CrtBreakAlloc to locate where the memory is being allocated, it points me to this line:

    Code:
    CString pathname = ptp->m_pathname;
    This leak had me going quite crazy -- after all, it was a local variable, placed on the stack, and when the thread exits, everything on the stack should be removed... right? Apparently not. Unless AfxEndThread() is called at the very end of your function, local variables will not be automatically destroyed. Fortunately there was someone who was as interested in this problem as I was, and he was the one that ultimately had it figured out, and the fix to this problem is to just
    Code:
    return 0;
    because that will take care of the removal of local variables.

    I thought I would share this information with all of you...

    Matt Schaller
    matt@swfla.rr.com
    Reply With Quote
      #2    
    Old February 26th, 2004, 12:02 AM
    Member
     
    Join Date: Apr 2002
    Posts: 86
    Myself dot NET is an unknown quantity at this point (<10)
    I know this is not relevant to your point, and your code sample is slimmed down, but your access to the g_bStopThread variable by two threads simultaneously is not thread-safe unless using interlocked functions or surrounded by a critical section or synchronization object. Just thought that should be noted. But you probably just didn't include that because it's not the issue here.
    Reply With Quote
      #3    
    Old February 26th, 2004, 01:29 AM
    Junior Member
     
    Join Date: Feb 2004
    Posts: 6
    Matt Schaller is an unknown quantity at this point (<10)
    I thought that since the setting of a variable that is less than 32 bits in length requires only one machine instruction (correct me if I am wrong on this), there is no problem with synchronization because accessing variables in two threads becomes a problem when the mode of access requires two or more machine instructions.

    Thank you for pointing that out... but I am careful when it comes to non-32bit values, such as STL vectors, in which case I use a critical section.

    Matt Schaller
    matt@swfla.rr.com

    Last edited by Matt Schaller; February 26th, 2004 at 01:31 AM.
    Reply With Quote
      #4    
    Old February 29th, 2004, 08:01 PM
    Member
     
    Join Date: Apr 2002
    Posts: 86
    Myself dot NET is an unknown quantity at this point (<10)
    You are probably correct, but it is not safe to assume that in general. If Windows is running on a different architecture, that might not be true. The general rule is to surround access to any (non-readonly) data by two or more threads by critical sections or synchronization objects, or use the interlocked functions.

    Additional note: even for accessing 32-bit values, the compiler may generate code where it is not one instruction for accessing/setting the variable. For example, use of an intermediate register. If one thread is preempted before the value is updated in memory, you will have corrupted data.

    Last edited by Myself dot NET; February 29th, 2004 at 08:13 PM.
    Reply With Quote
      #5    
    Old June 8th, 2005, 08:56 AM
    Junior Member
     
    Join Date: Jun 2005
    Posts: 1
     
    Re: Never use AfxEndThread!

    it's not the issue whether it's a 32bit variable or not
    the fact is that it should be mutexed,
    however, since the worker thread doesn't change the variable you can do something else:
    the main application keeps the int
    and gives the thread a const boolean *stopThread
    there's no need in a mutex because:
    a. there is only one writer
    b. the mutual data cannot be in an "Illegal" state*




    * such as if you'd had a char[100] used as a string and the writer could change the length of the actual string wich might prevent the thread from finding the string's null termination
  • 相关阅读:
    成功破解校园网锐捷客户端,实现笔记本无线网卡wifi
    献给正在郁闷的人们
    用友客户通,无法打开登录 'turbocrm' 中请求的数据库。登录失败。
    如何得到cxgrid的当前编辑值
    cxgrid当底层数据集为空时显示一条空记录
    使用nlite将SCSI RAID 阵列驱动整合到系统安装光盘内
    开始菜单的运行没有了
    Delphi代码获取网卡物理地址三种方法
    登录用友通模块时提示:运行时错误'430',类不支持自动化或不支持期望的接口 ...
    CentOS7下安装MySQL Mr
  • 原文地址:https://www.cnblogs.com/cy163/p/1900839.html
Copyright © 2011-2022 走看看