线程通信初探

原创 2000年12月28日 16:59:00
    进程是运行中的程序,有独立的内存,文件句柄和其它的系统资源,一个独立的进程可以包含多条执行路径,即线程。一个函数可以被多个线程访问,多个线程可以访问同一个全局变量。
    Windows提供两种线程,用户界面线程和辅助线程。用户界面线程有窗口,因此有自己的消息循环,辅助线程没有窗口,不需要处理消息。但是辅助线程非常有用而且很容易编程,比如程序在某个运行时间要完成多个(很笨重的)任务时,显然,辅助线程的使用会使程序的运行效率大大的提高。但是,线程间的通信是一个必须解决的问题。
    下面我们就来讨论一下线程间的通信的问题:
   一.线程的管理
     1.线程的启动:
       在使用辅助线程时,我们必须为线程写一个全局函数,它的返回值必须为   UINT类型,而且必须有LPVOID类型的参数,启动线程调用下面的函数:
    CWinThread* pThread=AfxBeginThread(
                        AFX_THREADPPOC ThreadProc,
                        LPVOID pParam,
                        int nPriority,
                        UINT nStackSize,
                        DWORD dwCreateFlags,
                        LPSECURITY_ATTRIBUTES lpSecurityAttrs);
    全局函数必须定义为 UINT ThreadProc(LPVOID pParam);
    AfxBeginThread会立即返回一个指向新创建的线程对象的指针,用来管理线  程,包括挂起和恢复线程的运行,但是线程对象没有成员函数来中止线程的运  行。AfxBeginThread的第二个参数是一个32位的值,用来传给全局函数;第三  个参数用来设定线程的优先级;而第四和第六个参数用来指定线程堆栈大小和  安全性,一般采用默认值0;第五个参数用来设定创建线程对象的方式,0为立  即执行,CREATE_SUSPEND为线程通过ResumeThread后才执行。
    而线程优先级的设置和获得可以通过下面的两个函数来实现:
    pThread->SetThreadPriority(THREAD_PRIORITY_ABOVE_NOMAL);和
    int nPriority=pThread->GetThreadPriority();
    2.线程的中止:
      可以调用MFC的AfxEndThread函数;
    3.检查线程是否结束:
      调用API函数GetExitCodeThread,
           DWORD ExitCode ;
           ::GetExitCodeThread(pThread->m_hThread,&ExitCode );
           if(ExitCode==STILL_ACTIVE)
               //运行中
           else   //线程已经中止
    二.主线程和辅助线程的通信
      主线程和辅助线程间的通信方式有很多种,最简单的就是利用全局变量。    这里利用消息通信是行不通的,因为辅助线程没有消息循环,不能够利用       Windows消息。
      下面我们用一个例子来说明。在例子中,我们写一个非常笨的函数,如实  现500*3000*3000的加法数据处理函数Add(int nCount);
  我们在对话框上放置Start、Cancel按钮和一个用来表示数据处理进度的进度条  。
    1.利用全局变量来实现主线程和辅助线程的通信:
     我们编写全局函数如下:
          UINT ThreadProc(LPVOID pParam)
          {
              nCount=0;//全局变量
              while(nCount<500)
              {
                 Add(nCount);
                 ::InterlockedIncrement((long*)&ncount);
               }
               return 0;
          }
      函数InterlockIncrement阻塞其它的线程,当计数器递增时防止其它的线程访问nCount。
     2.利用消息实现辅助线程和主线程的通信:
      主线程有一个窗口,有消息循环,我们可以在调用AfxBeginThread时把窗口句柄传递给辅助线程,我们通过post方式传递消息,在函数退出时,给窗口发送一个消息。
        重新编写线程函数如下:
          int nCount=0;
          UINT ThreadProc(LPVOID pParam)
          {
           while(nCount<500)
           {
            ::InterlockedIncrement((long*)&ncount);
            Add(nCount);
           }
           ::PostMessage(
            (HWND)pParam,
            WM_THREADFINISHED,//用户自定义消息
            0,0);
            return 0;
          }
        编写OnStart函数:
          void CThreadDlg::OnStart()
          {
           m_nTimer=SetTimer(1,100,NULL);//0.1秒
           ASSERT(m_nTimer!=0);
           GetDlgItem(IDC_START)->EnableWindow(FALSE);
           AfxBeginThread(ThreadProc,GetSafeHwnd(),THREAD_PROIRITY_NOMAL);
          }
        编辑OnCancel函数如下:
          void CThreadDlg::OnCancel()
          {
           if(nCount==0)
              CDialog::OnCancel();
           else nCount=500;
          }
        处理OnThreadFinished函数
          HRESULT CThreadDlg::OnThreadFinished(WPARAM wParam,LPARAM lParam)
          {
           CDialog::OnOk();
           return 0;
          }
      3.用事件使线程同步:
       利用WaitForSingleObject函数
       在stdafx.h中写入下面一行
       #include <afxmt.h>//由于使用了事件
       声明两个全局变量
          CEvent m_start,m_kill;
       在初始化函数中启动线程;
       重新编写OnStart函数:
          void CThreadDlg::OnStart()
          {
           m_nTimer=SetTimer(1,100,NULL);//0.1秒
           ASSERT(m_nTimer!=0);
           GetDlgItem(IDC_START)->EnableWindow(FALSE);
           m_start.SetEvent();
          }        
        重新编辑OnCancel函数如下:
          void CThreadDlg::OnCancel()
          {
           if(nCount==0)
              m_start.SetEvent();
           else m_kill.SetEvent();
           }
           编写全局函数如下:
          UINT ThreadProc(LPVOID pParam)
          {
           ::WaitForSingleObject(m_start,INFINITE);
           while(nCount<500)
           {
            Add(nCount);
            if(::WaitForSingleObject(m_start,0)=WAIT_OBJECT_0)
                break;
           }
           ::PostMessage(
            (HWND)pParam,
            WM_THREADFINISHED,//用户自定义消息
            0,0);
            return 0;
          }         
        其中第一个WaitForSingleObject的调用等待启动事件,INFINITE使其等待直到启动事件有信号。第二个调用若有信号,立即返回,中止线程。

多线程之同步线程通信小例子

最近在学习多线程的时候,看到这样的一个问题:有两个线程,一个是子线程,一个是主线程,子线程运行10次,接着主线程运行20次,接着子线程运行10,主线程运行20次,依次交替循环20次。刚开始看到这个问题...
  • zknxx
  • zknxx
  • 2016年11月15日 23:21
  • 638

GCD线程间通信及合成图片、获取验证码

本文来自简书,原文地址:http://www.jianshu.com/p/4ac227e763fa GCD Grand Central Dispatch (GCD) 是 Apple 开发的...
  • qq_30513483
  • qq_30513483
  • 2017年03月12日 15:57
  • 316

大数据初探

一、什么是大数据 5V特点(IBM提出):Volume(大量)、Velocity(高速)、Variety(多样)、Value(价值)、Veracity(真实性)。 应用:发现隐藏事物、商品相似性推荐、...
  • shuke1991
  • shuke1991
  • 2016年05月18日 19:00
  • 218

线程之间的通信(主要windows下message)

线程的通信无非是那么几种,下面进行简短介绍,然后将windows下的线程通信进行个人介绍。 线程通信的方法: 先吃饭~...
  • wangqing008
  • wangqing008
  • 2013年12月17日 11:29
  • 888

进程间通信与线程间通信 . windows下多线程通信方法 Linux 多线程通信

操作系统的主要任务是管理计算机的软件、硬件资源。现代操作系统的主要特点是多用户和多任务,也就是程序的并行执行,windows如此linux也是如此。所以操作系统就借助于进程来管理计算机的软、硬件资源,...
  • slj_win
  • slj_win
  • 2016年03月08日 10:11
  • 1019

操作系统---进程/线程 间通信

进程间通信 三个问题: 进程间的信息传递方式 对共享变量的访问 进程间执行顺序的问题 竞争条件:多个进程访问共享变量,结果取决于进程运行时的精确时序。 临界区: 互斥访问 忙等待互斥:屏蔽中...
  • hust_dxxxd
  • hust_dxxxd
  • 2016年07月18日 00:35
  • 214

多线程学习10-GCD的线程间通信

学习多线程10(之前跟着小码哥视频学习了多线程,准备把学到的东西放到网上,便于参考。仅有视频,所以所有文字都是自己打的,同时也温习一下多线程) GCD的线程间通信,简单事例(下载图片)。 #i...
  • Leemin_ios
  • Leemin_ios
  • 2016年04月19日 21:08
  • 1087

cocos2d-x线程通信(msg)

上次说到了多线程,这次来说说线程之间的消息传递~ ios中有通知中心NSNotificationCenter,在cocos2dx中也做了相应的封装CCNotificationCenter,但是它不是线...
  • guochuanqi
  • guochuanqi
  • 2013年12月09日 11:23
  • 2232

小白...

初入软件行业,代码小白一枚...还望各位大牛指点迷津,多谢多谢.
  • taoxiaowu36
  • taoxiaowu36
  • 2016年06月25日 22:25
  • 129

java线程通信的三种方式

1、传统的线程通信。     在synchronized修饰的同步方法或者修饰的同步代码块中使用Object类提供的wait(),notify()和notifyAll()3个方法进行线程通信。    ...
  • hpp1314520
  • hpp1314520
  • 2017年07月04日 15:25
  • 323
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:线程通信初探
举报原因:
原因补充:

(最多只允许输入30个字)