`
hme53hme
  • 浏览: 10470 次
社区版块
存档分类
最新评论

使用 C++ 和 MFC 进行多线程编程

 
阅读更多

使用 C++ 和 MFC 进行多线程编程
2010年11月01日
  Microsoft 基础类 (MFC) 库提供多线程应用程序支持。本主题描述进程、线程和 MFC 多线程编程方法。 进程是应用程序的执行实例。例如,双击"记事本"图标时,将启动运行"记事本"的进程。
  线程是进程内的执行路径。启动"记事本"时,操作系统创建进程并开始执行该进程的主线程。此线程终止时,进程也终止。启动代码以函数地址的形式将此主线程提供给操作系统。通常是所提供的 main 函数或 WinMain 函数的地址。
  如果愿意,可以在应用程序中创建其他线程。如果在处理后台任务或维护任务时不希望用户等待这些任务完成,则可能需要创建其他线程。MFC 应用程序中的所有线程都由 CWinThread 对象表示。大多数情况下,甚至不必显式创建这些对象,而只需调用框架 Helper 函数 AfxBeginThread,该函数将为您创建 CWinThread 对象。
  MFC 区分两种类型的线程:用户界面线程和辅助线程。用户界面线程通常用于处理用户输入及响应用户生成的事件和消息。辅助线程通常用于完成不需要用户输入的任务(如重新计算)。Win32 API 不区分线程类型;它只需要了解线程的起始地址以开始执行线程。MFC 为用户界面中的事件提供消息泵,从而对用户界面线程进行专门处理。CWinApp 是用户界面线程对象的一个示例,因为它从 CWinThread 派生并对用户生成的事件和消息进行处理。 应特别注意以下情况:可能有不止一个线程需要访问同一对象。多线程编程:编程提示 介绍了一些可以避免在这些情况下可能发生的问题的技术。多线程编程:如何使用同步类说明如何使用可用的类从多个线程同步访问一个对象。 编写和调试多线程编程本身是一项复杂棘手的任务,因为您必须确保一次只能有一个线程访问对象。多线程编程主题没有讲述多线程编程的基础知识,而只是说明了如何在多线程程序中使用 MFC。Visual C++ 中包含的多线程 MFC 示例阐释了几种多线程"添加功能"和 MFC 中未包含的 Win32 API,但只是一些入门知识。
  有关操作系统如何处理进程和线程的更多信息,请参见 Platform SDK 中的进程和线程。
  用户界面线程通常用于处理用户输入和响应用户事件,这些行为独立于执行该应用程序其他部分的线程。已经创建并启动主应用程序线程(在 CWinApp 导出的类中提供)。本文描述创建其他用户界面线程所需的步骤。
  创建用户界面线程时,必须首先从 CWinThread 派生类。必须使用 DECLARE_DYNCREATE 和 IMPLEMENT_DYNCREATE 宏声明并实现此类。此类必须重写某些函数,也可以重写其他函数。下表列出了这些函数及其用途。 函数 用途
  ExitInstance 线程终止时执行清除。通常重写。 InitInstance 执行线程实例初始化。必须重写。 OnIdle 执行线程特定的闲置时间处理。通常不重写。 PreTranslateMessage 将消息调度到 TranslateMessage 和 DispatchMessage 之前对其进行筛选。通常不重写。 ProcessWndProcException 截获由线程的消息和命令处理程序引发的未处理异常。通常不重写。 Run 控制线程的函数。包含消息泵。一般不重写。 MFC 通过参数重载提供两个版本的 AfxBeginThread:一个用于用户界面线程,另一个用于辅助线程。若要启动用户界面线程,请调用 AfxBeginThread,提供下列信息: 从 CWinThread 派生的类的 RUNTIME_CLASS。 (可选)所需的优先级级别。默认值为正常优先级。有关可用的优先级级别的更多信息,请参见 Platform SDK 中的 SetThreadPriority。 (可选)所需的线程堆栈大小。默认值与创建线程的堆栈大小相同。 (可选)CREATE_SUSPENDED,如果希望在挂起状态中创建线程。默认值为 0,即正常启动线程。 (可选)所需的安全属性。默认值与父线程具有相同的访问权。有关此安全信息格式的更多信息,请参见 Platform SDK 中的 SECURITY_ATTRIBUTES。 AfxBeginThread 为您完成大部分工作。它创建类的新对象、使用您提供的信息初始化该对象并调用 CWinThread::CreateThread 开始执行线程。在整个过程中进行检查,确保假如创建过程的任何部分出现故障,所有对象都能被正确地解除分配。
  MFC 提供的多线程类分为两类:同步对象(CSyncObject、CSemaphore、CMutex、CCriticalSection 和 CEvent)和同步访问对象(CMultiLock 和 CSingleLock)。
  当必须控制对资源的访问以确保资源的完整性时,使用同步类。同步访问类用于获取对这些资源的访问权。本主题介绍各个类的适用情况。
  若要确定应使用的同步类,请询问以下一系列问题: 应用程序必须等到发生某事才能访问资源(例如,在将数据写入文件之前,必须先从通信端口接收它)吗?
  如果是,请使用 CEvent。 同一应用程序内一个以上的线程可以同时访问此资源(例如,应用程序允许在同一文档上最多同时打开五个带有视图的窗口)吗?
  如果是,请使用 CSemaphore。 可以有一个以上的应用程序使用此资源(例如,资源在 DLL 中)吗?
  如果是,请使用 CMutex。
  如果不是,请使用 CCriticalSection。 从不直接使用 CSyncObject。它是其他四个同步类的基类。 以维护链接的帐户列表的应用程序为例。此应用程序允许在独立的窗口中最多检查三个帐户,但是在任何特定的时间,只能更新一个帐户。更新帐户后,通过网络将更新的数据发送到数据存档。
  此示例应用程序使用所有这三种类型的同步类。因为它一次最多允许检查三个帐户,因此使用 CSemaphore 限制对三个视图对象的访问。当试图查看第四个帐户时,应用程序或者等到前三个窗口中有一个关闭,或者该尝试失败。更新帐户时,应用程序使用 CCriticalSection 确保一次只更新一个帐户。更新成功后,发出信号 CEvent 以释放等待该事件信号发送的线程。此线程将新数据发送到数据存档。 选择要使用的同步访问类更为简单。如果应用程序只与访问单个受控资源有关,请使用 CSingleLock。如果需要访问多个受控资源中的任何一个,则使用 CMultiLock。在示例 1 中,应使用 CSingleLock,因为在每种情况下,任何特定时间都只需要一个资源。 有关如何使用同步类的信息,请参见多线程处理:如何使用同步类。有关同步的信息,请参见 Platform SDK 中的同步。有关 MFC 中多线程处理支持的信息,请参见使用 C++ 和 MFC 进行多线程处理。 转自:http://hi.baidu.com/crearmore/blog/item/ae9a158207 29a5a50df4d230.html
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics