记得用MFC做了一个图像自动修复软件,当时没有多线程操作这一概念,由于图像修复算法比较复杂,因此,当执行图像修复时,程序就像卡死了似得而不能做其他操作。其实MFC对这种情况有一种很好地解决方案,那就是采用多线程编程技术。以图像修复算法为例,由于其本身需要耗费大量时间,因此我们可以单独开一个线程让他执行修复而不影响主程序的操作。

关于线程的一些概念,以及在VS2013下的实例:

MFC中有两类线程,分别称之为工作者线程和用户界面线程。二者的主要区别在于工作者线程没有消息循环,而用户界面线程有自己的消息队列和消息循环。

工作者线程没有消息机制,通常用来执行后台计算和维护任务,如冗长的计算过程(正适合图像修复算法),打印机的后台打印等。用户界面线程一般用于处理独立于其他线程执行之外的用户输入,响应用户及系统所产生的事件和消息等。但对于Win32的API编程而言,这两种线程是没有区别的,它们都只需线程的启动地址即可启动线程来执行任务。

这两类线程的创建:

用户界面线程的AfxBeginThread

用户界面线程的AfxBeginThread的原型如下:
CWinThread* AFXAPI AfxBeginThread(   CRuntimeClass* pThreadClass,   int nPriority,   UINT nStackSize,   DWORD dwCreateFlags,   LPSECURITY_ATTRIBUTES lpSecurityAttrs)
其中:
参数1是从CWinThread派生的RUNTIME_CLASS类;
参数2指定线程优先级,如果为0,则与创建该线程的线程相同;
参数3指定线程的堆栈大小,如果为0,则与创建该线程的线程相同;
参数4是一个创建标识,如果是CREATE_SUSPENDED,则在悬挂状态创建线程,在线程创建后线程挂起,否则线程在创建后开始线程的执行。
参数5表示线程的安全属性,NT下有用。

工作者线程的AfxBeginThread

工作者线程的AfxBeginThread的原型如下:
CWinThread* AfxBeginThread(AFX_THREADPROC pfnThreadProc,   LPVOID lParam,   int nPriority = THREAD_PRIORITY_NORMAL,   UINT nStackSize = 0,   DWORD dwCreateFlags = 0,   LPSECURITY_ATTRIBUTES lpSecurityAttrs = NULL   );//用于创建工作者线程
返回值: 成功时返回一个指向新线程的线程对象的指针,否则NULL。
pfnThreadProc : 线程的入口函数,声明一定要如下: UINT MyThreadFunction(LPVOID pParam),不能设置为NULL;
pParam : 传递入线程的参数,注意它的类型为:LPVOID,所以我们可以传递一个结构体入线程.
nPriority : 线程的优先级,一般设置为 0 .让它和主线程具有共同的优先级.
nStackSize : 指定新创建的线程的栈的大小.如果为 0,新创建的线程具有和主线程一样的大小的栈
dwCreateFlags : 指定创建线程以后,线程有怎么样的标志.可以指定两个值:
CREATE_SUSPENDED : 线程创建以后,会处于挂起状态,直到调用:ResumeThread
0 : 创建线程后就开始运行.
lpSecurityAttrs : 指向一个 SECURITY_ATTRIBUTES 的结构体,用它来标志新创建线程的安全性.如果为 NULL,
那么新创建的线程就具有和主线程一样的安全性.
如果要在线程内结束线程,可以在线程内调用 AfxEndThread.结束线程的两种方式
 
VS2013实例:
创建一个线程执行函数(一般定义在类外)

UINT MyThread(LPVOID pParam)
{
int ThreatEvent = *(int* )pParam;
if (ThreatEvent == )
AfxMessageBox(_T("MyThreadProc"), MB_OK);return ;
}

强调一下这个LPVOID pParam,其可以传递任何简单的数据类型。但是必须得传递全局或者静态变量(这个不清楚是为什么);

接下来开启线程:

static int k;
k = ;
AfxBeginThread(MyThread, &k);

这个可以在OnShowWindow下测试一下。

多线程之间的通信:

通常情况下,一个次级线程要为主线程完成某种特定类型的任务,这就隐含着表示在主线程和次级线程之间需要建立一个通信的通道。一般情况下,有下面的几种方法实现这种通信任务:使用全局变量(这个看起来很LOW)、使用事件对象、使用消息。

线程同步

虽然多线程能给我们带来好处,但是也有不少问题需要解决。例如,对于像磁盘驱动器这样独占性系统资源,由于线程可以执行进程的任何代码段,且线程的运行是由系统调度自动完成的,具有一定的不确定性,因此就有可能出现两个线程同时对磁盘驱动器进行操作,从而出现操作错误;又例如,对于银行系统的计算机来说,可能使用一个线程来更新其用户数据库,而用另外一个线程来读取数据库以响应储户的需要,极有可能读数据库的线程读取的是未完全更新的数据库,因为可能在读的时候只有一部分数据被更新过。使隶属于同一进程的各线程协调一致地工作称为线程的同步。MFC提供了多种同步对象,下面我们只介绍最常用的四种:

临界区(CCriticalSection)
事件(CEvent)
互斥量(CMutex)
信号量(CSemaphore)
 
通过这些类,我们可以比较容易地做到线程同步。
 
 

MFC的多线程操作的更多相关文章

  1. C#中级-常用多线程操作(持续更新)

    一.前言       多线程操作一直是编程的常用操作,掌握好基本的操作可以让程序运行的更加有效.本文不求大而全,只是将我自己工作中常常用到的多线程操作做个分类和总结.平时记性不好的时候还能看看.本文参 ...

  2. java多线程操作

    进程是程序的一次动态的执行过程,它经历了从代码加载.执行完毕的一个完整过程,这个过程也是进程本身从产生.发展到最终消亡的过程. 多线程是实现并发机制的一种有效的手段.进程和线程一样,都是实现并发的一个 ...

  3. 更高效地提高redis client多线程操作的并发吞吐设计

    Redis是一个非常高效的基于内存的NOSQL数据库,它提供非常高效的数据读写效能.在实际应用中往往是带宽和CLIENT库读写损耗过高导致无法更好地发挥出Redis更出色的能力.下面结合一些redis ...

  4. C#多线程操作界面控件的解决方案(转)

    C#中利用委托实现多线程跨线程操作 - 张小鱼 2010-10-22 08:38 在使用VS2005的时候,如果你从非创建这个控件的线程中访问这个控件或者操作这个控件的话就会抛出这个异常.这是微软为了 ...

  5. c# BackGroundWorker 多线程操作的小例子

    在我们的程序中,经常会有一些耗时较长的运算,为了保证用户体验,不引起界面不响应,我们一般会采用多线程操作,让耗时操作在后台完成,完成后再进行处理或给出提示,在运行中,也会时时去刷新界面上的进度条等显示 ...

  6. swift语言之多线程操作和操作队列(下)———坚持51天吃掉大象(写技术文章)

    欢迎有兴趣的朋友,参与我的美女同事发起的活动<51天吃掉大象>,该美女真的很疯狂,希望和大家一起坚持51天做一件事情,我加入这个队伍,希望坚持51天每天写一篇技术文章.关注她的微信公众号: ...

  7. C# winform编程中多线程操作控件方法

    private void Form1_Load(object sender, EventArgs e) { Thread newthread = new Thread(new ThreadStart( ...

  8. sqlite:多线程操作数据库“database is locked”解决方法(二)

    上一篇博客<sqlite:多线程操作数据库“database is locked”解决方法>通过注册延时函数的方法来处理数据库被锁的问题.此方法固然能解决问题,但是在多个线程向数据库写入大 ...

  9. 多线程操作(循环往listbox中添加数据)

    一.先造一个窗体,其中就开始按钮,暂停按钮,以及listbox文本框 二.当点击开始的时候,数据会无限的往listbox中加,为了防止卡住和提升效率,便造了一个新的线程来执行开始操作 namespac ...

随机推荐

  1. UITableViewController和XML解析还有地图的简单结合

    然后我的代码就按照上面的这个顺序输出. #import <Foundation/Foundation.h> #import <MapKit/MapKit.h> @interfa ...

  2. Android自定义控件(二)

    这一篇主要来讲一下自定义控件中的自定义viewgroup,我们以项目中最常用的下拉刷新和加载更多组件为例 简单介绍一下自定义viewgroup时应该怎么做. 分析:下拉刷新和加载更多的原理和步骤 自定 ...

  3. Session 失效原因

    转载http://blog.csdn.net/LLorJJ999/article/details/4107464 昨天去GTSC面试,有面试官问我关于Session丢失之后怎么查的问题,说老实话,开发 ...

  4. 《C#高级编程》读书笔记

    <C#高级编程>读书笔记 C#类型的取值范围 名称 CTS类型 说明 范围 sbyte System.SByte 8位有符号的整数 -128~127(−27−27~27−127−1) sh ...

  5. SQL SERVER 2008 Reporting Services 的一些小问题集合

    实验环境:服务器  Windows Server  2008 R2 Standard 64bit                   数据库  SQL SERVER 2008 R2 Standard ...

  6. dragsort html拖拽排序

    一.Jquery List DragSort 对于有些页面,如首页的定制,需要进行动态的拖拽排序.由于自己实现比较困难,我们一般会使用一些js插件来实现.dragsort 就是帮助我们完成这一需求.通 ...

  7. andrioid 分享到其它(短信,qq,微信等功能)

    public static void share(Context context, String text) { Intent intent = new Intent(Intent.ACTION_SE ...

  8. Netruon 理解(11):使用 NAT 将 Linux network namespace 连接外网

    学习 Neutron 系列文章: (1)Neutron 所实现的虚拟化网络 (2)Neutron OpenvSwitch + VLAN 虚拟网络 (3)Neutron OpenvSwitch + GR ...

  9. C#/winform 自动触发鼠标、键盘事件

    要在C#程序中触发鼠标.键盘事件必须要调用windows函数. 一.鼠标事件的触发 1.引用windows函数mouse_event /// <summary> /// 鼠标事件 /// ...

  10. 【2016-11-6】【坚持学习】【Day21】【子窗口关闭时,同步关闭它的主窗口(方法二)】

    根据上文,在子窗口设置一个委托.然后在子窗口关闭事件,执行委托实例,然后在主窗口增加监听委托的方法.... 想想,本事关闭事件就是一个特殊的委托.那么干嘛还要特意去声明一个新的呢?多此一举. 于是有下 ...