多线程处理:在 MFC 中创建工作线程

工作线程通常用于处理后台任务,用户不必等待其继续使用应用程序。 重新计算和后台打印等任务是工作线程的好例子。 本主题详细介绍了创建工作线程所需的步骤。 主题包括:

创建工作线程相对简单。 只需完成两步就能使线程运行:实现控制函数并启动线程。 无需从 CWinThread 获取类。 如果需要特殊版本的 CWinThread,则可以获取类,但对于大多数简单工作线程来说,这不是必需的。 无需修改即可使用 CWinThread

启动线程

有两个重载版本的 AfxBeginThread:一个只能创建工作线程,一个既可创建用户界面线程也可创建工作线程。 若要使用第一个重载开始执行工作线程,请调用 AfxBeginThread,并提供以下信息:

  • 控制函数的地址。

  • 要传递给控制函数的参数。

  • (可选)想要的线程优先级。 默认为正常优先级。 有关可用优先级级别的详细信息,请参阅 Windows SDK 中的 SetThreadPriority

  • (可选)所需的线程堆栈大小。 默认为与创建线程时相同的堆栈大小。

  • (可选)CREATE_SUSPENDED,如果希望线程在挂起状态下创建的话。 默认为 0,否则正常启动线程。

  • (可选)所需的安全属性。 默认为与父线程具有相同的访问使用情况。 有关此安全信息格式的详细信息,请参阅 Windows SDK 中的 SECURITY_ATTRIBUTES

AfxBeginThread 为你创建和初始化 CWinThread 对象,启动对象,并返回其地址以便你稍后可以引用它。 在整个过程中都会进行检查,以确保在创建的任何部分失败时正确解除分配所有对象。

实现控制函数

控制函数定义线程。 输入此函数时,线程启动,退出时线程终止。 此函数应具有以下原型:

UINT MyControllingFunction( LPVOID pParam );

该参数是单个值。 函数在此参数中接收的值是创建线程对象时传递给构造函数的值。 控制函数可以采用它选择的任何方式解释此值。 可将它视为标量值或指向包含多个参数的结构的指针,也可以忽略它。 如果参数引用结构,则结构不仅可用于将数据从调用方传递到线程,还可用于将数据从线程传回调用方。 如果使用此类结构将数据传回调用方,则线程需要在结果准备就绪时通知调用方。 有关从工作线程传到调用方的信息,请参阅多线程处理:编程提示

函数终止时,应返回指示终止原因的 UINT 值。 通常,此退出代码为 0 表示成功,其他值指示不同类型的错误。 这完全依赖于实现。 某些线程可以维护对象的使用数,并返回该对象的当前使用数。 若要查看应用程序如何检索此值,请参阅多线程处理:终止线程

使用 MFC 库编写的多线程程序可以执行的操作存在一些限制。 有关这些限制的说明以及有关使用线程的其他提示,请参阅多线程处理:编程提示

控制函数示例

以下示例演示如何定义控制函数并从程序的其他部分使用它。

UINT MyThreadProc( LPVOID pParam )
{
    CMyObject* pObject = (CMyObject*)pParam;

    if (pObject == NULL ||
        !pObject->IsKindOf(RUNTIME_CLASS(CMyObject)))
    return 1;   // if pObject is not valid

    // do something with 'pObject'

    return 0;   // thread completed successfully
}

// inside a different function in the program
.
.
.
pNewObject = new CMyObject;
AfxBeginThread(MyThreadProc, pNewObject);
.
.
.

你想进一步了解什么?

另请参阅

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