多线程与AfxGetMainWnd的吐血遭遇……

把之前用VC6写的MFC工程升级到VC2005后,编译运行就崩溃,莫名其妙,问了ZV说是经常出现这种问题,要重新建立个工程拖代码才行,那好吧,就重来,折腾了好久,还是……又崩溃了……

这下头大了,同样的代码,VC6里正常,VC2005反而崩溃?尝试关闭连接的多种选项,除了出现莫名其妙的LNK ERROR以外一无所获,最后F8逐步调试,发现在_beginthread后的WaitForSingleObject处崩溃了,这么神奇?注释掉WaitForSingleObject,依然崩溃,在群里讨论半天也没可行结果,后来尝试去掉多线程,直接调用过程,太牛逼了,这下运行完好!

想想可能引起崩溃的原因有很多,比较容易接受的是多线程时传参丢失,因为在VC2005即时显示当前数据内容里看到似乎有点数据不太正确,但是经过一番折腾后问题依旧,用afxMessageBox弹出来却又是正常的数据,头都大了!

然后想到把参数写成固定的看看……依然崩溃,天啊!

折腾了一晚上都没结果,头都晕了,明天还有事情做,只好睡觉。

今晚忙完回来,不服,继续开VC8折腾!想想是不是_beginthread得改改,写成CreateThread,直接报错:

错误 4 error C2664: “CreateThread”: 不能将参数 3 从“DWORD (__stdcall *)(LPVOID *)”转换为“LPTHREAD_START_ROUTINE”

写成_beginthreadex,嗯,不报错了好像……

hThread=(HANDLE)_beginthreadex(NULL,0,(PBEGINTHREADEX_THREADFUNC)StressThread,(LPVOID)thread_info,0, (PBEGINTHREADEX_THREADID)&dwThreadID);

满怀信心运行,依然崩溃!!!!!

今晚比昨晚有耐心,慢慢跟语句,终于到这里的时候:

  if(sendto(nSocket,request,strlen(request),0,NULL,0)==SOCKET_ERROR){
  ::AfxGetMainWnd()->SetWindowText(dlgTitle + " - 发送数据失败!");
  }else{
  lngPacketSent++;
  CString szPacketSent;
  szPacketSent.Format("已请求 %d 个连接",lngPacketSent);
  ::AfxGetMainWnd()->SetWindowText(dlgTitle + " - " + szPacketSent);
  }

突然崩溃了!

突然有个念头,把
  CString szPacketSent;
  szPacketSent.Format("已请求 %d 个连接",lngPacketSent);
  ::AfxGetMainWnd()->SetWindowText(dlgTitle + " - " + szPacketSent);
全注释掉!再次运行,居然平安无事……

点停止……又崩溃了……
停止的代码是这个:

void CWebStressMFCDlg::OnBnClickedbtnattack()

{

  CString sBtnText;

  m_btnAttack.GetWindowText(sBtnText);

  if(sBtnText=="开始(&S)"){

  m_btnAttack.SetWindowText("停止(&S)");

  char szBuffer[1024];

  m_txtTarget.GetLine(0,szBuffer,1024);

  Target=(char *)szBuffer;

  bAttacking = true;

  dwThreadNum=0;

  dwThreadID=0;

  lngPacketSent = 0;

  ::AfxGetMainWnd()->SetWindowText(dlgTitle + " - 正在初始化");

  this->StartAttack();

  }else{

  m_btnAttack.SetWindowText("开始(&S)");

  bAttacking = false;

  dwThreadNum=0;

  dwThreadID=0;

  lngPacketSent = 0;

  ::AfxGetMainWnd()->SetWindowText(dlgTitle + " - 已停止");

  }

}

这里的相同点只有一个,那就是::AfxGetMainWnd()->SetWindowText,难道是这个语句出问题?太天方夜谭了吧!但是尝试将它屏蔽后却再也没崩溃过!

事情开始有点眉目了,似乎是开始多线程以后再调用::AfxGetMainWnd()->SetWindowText就会发生崩溃,但是为啥之前VC6里死活没问题?找了半天资料没答案,最后很幸运的在某个站点看到一个全英文回答:
If AfxGetMainWnd is called from the application's primary thread, it returns the application's main window according to the above rules. If the function is called from a secondary thread in the application, the function returns the main window associated with the thread that made the call.

在多线程里调用AfxGetMainWnd返回的是与线程有关联的主窗体?但是我这程序只有一个窗体,但是它仍然崩溃,差不多明白了,多线程里获得的句柄不等于真正的窗体句柄,对这个句柄进行“非法写操作”,于是崩溃了……

了解了症状就好办了,在全局里写一个窗口句柄类变量
CWnd* m_pCWnd;

然后在初始化过程OnInitDialog里加上
m_pCWnd = AfxGetMainWnd();

以后要写窗体标题的时候就用m_pCWnd->SetWindowText,将程序里所有AfxGetMainWnd改为m_pCWnd,重新编译运行,终于不再崩溃了!
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值