WEB开发网
开发学院软件开发VC 多线程管理类 阅读

多线程管理类

 2010-09-04 20:48:19 来源:WEB开发网   
核心提示:二、下面说明一下代码的内容其实创建线程的操作很简单,最令人烦不胜烦的地方是结束线程的代码,多线程管理类(4),一般其流程是:1.通知所以线程要结束2.等待所以线程结束通知其实倒挺好通知,问题是等待!第一个问题,但可恶的M$好像要放弃MFC,MFC一直没有什么大的改进,主线程界面,考虑的第一个函数是WaitForMult

二、下面说明一下代码的内容

其实创建线程的操作很简单,最令人烦不胜烦的地方是结束线程的代码。

一般其流程是:

1.通知所以线程要结束

2.等待所以线程结束

通知其实倒挺好通知,问题是等待!

第一个问题,主线程界面,考虑的第一个函数是WaitForMultipleObjects,问题是主线用这个函数等待子线程结束时,令主线程会处于休眠状态,如果等待时间长的话,程序就会像死了似的。于是把函数换为MsgWaitForMultipleObjects,令其每次只等待一个线程,而且将其参数bWaitAll设为FALSE,并在调用这个函数前,用PeekMessageLoop处理完Windows留下的消息,这样主界面看起来就不会出问题 。

第二个问题,句柄的复制,因为在MsgWaitForMultipleObjects里,需要输入要等待线程的句柄数组,但AfxBeginThread开启的线程,当线程结束后,其线程句柄就无效,句柄不能普通地赋值,只能用DuplicateHandle将其复制 。

第三个问题,提示,当主线程长时间等待子线程时,是不是应有个提示框之类的东西提示呢,然后主主界面的任何其它操作都不能用,就像我们平时用MessageBox时,我们只能先把这个Box去掉之后,才能操作界面的其它东西,但这里不用这个方法,这里只能Create一个非模态对话框,但这个框要达到像模态对话框的效果,我用spy++看了一下才看想到原来可以这样

//pWnd是主界面的指针
pWnd->EnableWindow(false);
//Create一个非模态对话框
//等待所以线程结束
pWnd->EnableWindow(true);
pWnd->ShowWindow(SW_RESTORE);

下面是主要代码:

bool EndAllThread(const char *szMsg)
{
  if (!m_pThread) return false;//线程句柄为空
  HANDLE pProcess=GetCurrentProcess();
  BOOL bRet;
  int i(0),nRet;
  HANDLE *pHandle=new HANDLE[m_nThreadCount];
  T *pWnd=static_cast<T *>(this);
  pWnd->EnableWindow(false);

  if (szMsg)
  {
    s_Waitdlg.m_strshow=szMsg;
    s_Waitdlg.SetCancelDisable();//使取消按钮无效
    s_Waitdlg.Create((char *)IDD_YGDIALOG_WAITING,pWnd);
    s_Waitdlg.CenterWindow(NULL);
    s_Waitdlg.ShowWindow(SW_SHOW);
  }
  for(i=0;i<m_nThreadCount;i++)
  {
    //将句柄复制
    bRet=DuplicateHandle(pProcess,m_pThread[i]->m_hThread,pProcess,&pHandle[i],DUPLICATE_SAME_ACCESS,
      true,DUPLICATE_SAME_ACCESS);
    //保证所复制的句柄都要有效
    if (!bRet)
    {
      Sleep(100);
      TRACE("----------------DuplicateHandle 失败!
");
      i--;continue;
    }
  }
  s_IsBreaking=true;//将线程结束
  i=0;
  //等待线程结束
  while (i!=m_nThreadCount)//直到所以线程的m_hThread都已经结束时则i==m_nThreadCount
  {
    for(i=0;i<m_nThreadCount;i++)
    {
      PeekMessageLoop();//先处理多余的Windows消息
      //这里一定要用MsgWaitForMultipleObjects,不能用WaitForMultipleObjects,因为这个不能处理消息
      nRet=MsgWaitForMultipleObjects(1,pHandle+i,false,INFINITE,QS_ALLEVENTS);
      TRACE("nRet=%d,i=%d
",nRet,i);
      if (nRet==WAIT_OBJECT_0+1) //只有消息Event,没有线程的Event
      {
        Sleep(20); //等会儿
        break;
      }
      if (nRet==WAIT_FAILED ) break;//发生错误,无须等待了
    }
    if (nRet==WAIT_FAILED ) break;
  }
  delete [] m_pThread;
  delete [] pHandle;
  m_pThread=NULL;
  m_nThreadCount=0;
  pWnd->EnableWindow(true);
  pWnd->ShowWindow(SW_RESTORE);
  if (IsWindow(s_Waitdlg.m_hWnd)) s_Waitdlg.DestroyWindow();
  if (nRet==WAIT_FAILED ) false;
  return true;
}

结束:

本人文笔不好,以上内容表达可能错漏百出,请各大蝦不要见笑,详细还是见代码吧,如程序有什么问题请用下面的方式联系。

无数遍想不搞MFC,搞界面用MFC确实麻烦,但又舍不得C++。看了几下搞界面好的Delphi,但它PASCAL语法实在让人难以接受,语法功能太弱,就连变量声明的位置都受到限制,操作符重载居然不支持,模板就更不用说了。用.net,把C++扩展了,搞得不知道像个什么样子,还不如用C#,但C#里没有了指针,内存申请了,还不能手动释放,可能我对C#的理解还是很肤浅吧。还是觉得C++是最好计算机语言,但可恶的M$好像要放弃MFC,MFC一直没有什么大的改进,有跟我志同道合的朋友欢迎跟我联系。

本文配套源码

上一页  1 2 3 4 

Tags:线程 管理

编辑录入:爽爽 [复制链接] [打 印]
赞助商链接