多线程处理:在 MFC 中创建工作线程Multithreading: Creating Worker Threads in MFC

工作线程通常用于处理后台任务, 用户无需等待即可继续使用应用程序。A worker thread is commonly used to handle background tasks that the user should not have to wait for to continue using your application. 重新计算和后台打印等任务就是工作线程的很好的例子。Tasks such as recalculation and background printing are good examples of worker threads. 本主题详细介绍了创建辅助线程所需的步骤。This topic details the steps necessary to create a worker thread. 包括以下主题:Topics include:

创建辅助线程是一个相对简单的任务。Creating a worker thread is a relatively simple task. 只需执行两个步骤就能使线程运行: 实现控制函数并启动线程。Only two steps are required to get your thread running: implementing the controlling function and starting the thread. 不需要从CWinThread派生类。It is not necessary to derive a class from CWinThread. 如果需要特殊版本的CWinThread, 则可以派生类, 但对于大多数简单的工作线程, 此方法不是必需的。You can derive a class if you need a special version of CWinThread, but it is not required for most simple worker threads. 无需修改CWinThread即可使用。You can use CWinThread without modification.

启动线程Starting the Thread

有两个重载版本AfxBeginThread: 一个只能创建辅助线程, 另一个可创建用户界面线程和工作线程。There are two overloaded versions of AfxBeginThread: one that can only create worker threads, and one that can create both user-interface threads and worker threads. 若要使用第一个重载开始执行工作线程, 请调用AfxBeginThread, 并提供以下信息:To begin execution of your worker thread using the first overload, call AfxBeginThread, providing the following information:

  • 控制函数的地址。The address of the controlling function.

  • 要传递到控制函数的参数。The parameter to be passed to the controlling function.

  • 可有可无线程所需的优先级。(Optional) The desired priority of the thread. 默认值为正常优先级。The default is normal priority. 有关可用优先级的详细信息, 请参阅 Windows SDK 中的参见 setthreadpriorityFor more information about the available priority levels, see SetThreadPriority in the Windows SDK.

  • 可有可无线程所需的堆栈大小。(Optional) The desired stack size for the thread. 默认值与创建线程的堆栈大小相同。The default is the same size stack as the creating thread.

  • 可有可无如果希望线程在挂起状态中创建, 则为 CREATE_SUSPENDED。(Optional) CREATE_SUSPENDED if you want the thread to be created in a suspended state. 默认值为 0, 或正常启动线程。The default is 0, or start the thread normally.

  • 可有可无所需的安全特性。(Optional) The desired security attributes. 默认值与父线程具有相同的访问权限。The default is the same access as the parent thread. 有关此安全信息的格式的详细信息, 请参阅 Windows SDK 中的SECURITY_ATTRIBUTESFor more information about the format of this security information, see SECURITY_ATTRIBUTES in the Windows SDK.

AfxBeginThread创建并初始化CWinThread对象, 启动对象, 并返回其地址, 以便以后可以引用它。AfxBeginThread creates and initializes a CWinThread object for you, starts it, and returns its address so you can refer to it later. 在整个过程中进行检查, 以确保在创建过程中的任何部分都不会正确释放所有对象。Checks are made throughout the procedure to make sure all objects are deallocated properly should any part of the creation fail.

实现控制函数Implementing the Controlling Function

控制函数定义线程。The controlling function defines the thread. 输入此函数后, 线程将开始, 并且在退出时, 线程终止。When this function is entered, the thread starts, and when it exits, the thread terminates. 此函数应具有以下原型:This function should have the following prototype:

UINT MyControllingFunction( LPVOID pParam );

参数是单个值。The parameter is a single value. 函数在此参数中接收的值是创建线程对象时传递给构造函数的值。The value the function receives in this parameter is the value that was passed to the constructor when the thread object was created. 控制函数可以通过它选择的任何方式解释此值。The controlling function can interpret this value in any manner it chooses. 它可以被视为标量值或指向包含多个参数的结构的指针, 也可以被忽略。It can be treated as a scalar value or a pointer to a structure containing multiple parameters, or it can be ignored. 如果参数引用结构, 则该结构不仅可用于将数据从调用方传递到线程, 还可以将数据从线程传递回调用方。If the parameter refers to a structure, the structure can be used not only to pass data from the caller to the thread, but also to pass data back from the thread to the caller. 如果使用此类结构将数据传递回调用方, 则在结果准备就绪时, 该线程需要通知调用方。If you use such a structure to pass data back to the caller, the thread needs to notify the caller when the results are ready. 有关从工作线程到调用方的通信的信息, 请参见多线程处理:编程提示For information about communicating from the worker thread to the caller, see Multithreading: Programming Tips.

当函数终止时, 它应返回指示终止原因的 UINT 值。When the function terminates, it should return a UINT value indicating the reason for termination. 通常, 此退出代码为 0, 表示成功, 并提供指示不同错误类型的其他值。Typically, this exit code is 0 to indicate success with other values indicating different types of errors. 这是纯粹依赖实现的。This is purely implementation dependent. 某些线程可以维护对象的使用计数, 并返回该对象的当前使用数量。Some threads might maintain usage counts of objects and return the current number of uses of that object. 若要查看应用程序如何检索此值, 请参阅多线程处理:终止线程To see how applications can retrieve this value, see Multithreading: Terminating Threads.

对于使用 MFC 库编写的多线程程序中的内容, 有一些限制。There are some restrictions on what you can do in a multithreaded program written with the MFC library. 有关这些限制的说明以及有关使用线程的其他提示, 请参阅多线程处理:编程提示For descriptions of these restrictions and other tips about using threads, see Multithreading: Programming Tips.

控制函数示例Controlling Function Example

下面的示例演示如何定义控制函数并从程序的其他部分使用它。The following example shows how to define a controlling function and use it from another portion of the program.

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);
.
.
.

你想进一步了解什么?What do you want to know more about?

请参阅See also

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