第344页 windows线程池
- 章节名:windows线程池
- 页码:第344页
windows提供了一个与I/O完成端口相配套的线程池机制来简化线程的创建,销毁和日常管理。但这个新的通用的线程池可能并不使用于所有的情况。 这些新的线程池函数允许我们做以下这些事情: 1.以异步的方式来调用一个函数 2.每隔一段时间调用一个函数 3.当内核对象触发的时候调用一个函数 4.当异步I/O请求完成的时候调用一个函数
当一个进程初始化的时候,它并没有任何与线程池有关的开销。但是,一旦调用了新的线程池函数,系统就会为进程创建相应的内核资源,其中一些资源在进程终止之前都一直存在。所以必须谨慎使用。 引自 windows线程池 情形1,以异步方式调用函数
为了用线程池来以异步方式执行一个函数,我们需要定义一个具有以下原型的函数: VOID NTAPI SimpleCallback(PTP_CALLBACK_INSTANCE pInstance, PVOID pvContext); 然后为了让线程池中的一个线程执行该函数,我们需要向线程池提交一个请求。为了达到这个目的,要调用TrySubmitThreadpoolCallback函数。该函数通过调用PostQueuedCompletionStatus将一个工作项(work item)添加到线程池的队列中。 引自 windows线程池 显式地控制工作项
某些情况下,比如内存不足或配额限制的时候,TrySubmitThreadpoolCallback调用可能会失败。每次调用TrySubmitThreadpoolCallback的时候,系统会在内部以我们的名义分配一个工作项。如果打算提交大量的工作项,那么处于对性能和内存使用的考量,创建工作项一次,然后分多次提交它会更好。 CreateThreadpoolWork来创建一个工作项。其中有个参数是函数指针,当线程池中的线程最终对工作项进行处理的时候,会调用该函数指针指向的函数。函数指针指向的函数必须符合以下函数原型: VOID CALLBACK WorkCallback( PTP_CALLBACK_INSTANCE Instance, PVOID Context, PTP_WORK Work ); 当我们想要向线程池提交一个请求的时候,可以调用SubmitThreadpoolWork。 如果我们有另一个线程,该线程想要取消已经提交的工作项,或者该线程由于要等待工作项处理完毕而需要将自己挂起,那么可以调用WaitForThreadpoolWorkCallback 不再需要一个工作项的时候,应该调用CloseThreadpoolWork。 引自 windows线程池 情形2,每隔一段时间调用一个函数
·为了将一个工作项安排在某个时间执行,我们必须定义一个回调函数,它的函数原型如下: VOID CALLBACK TimeoutCallback( PTP_CALLBACK_INSTANCE pInstance, PVOID pvContext, PTP_TIMER pTimer ) 然后调用下面的函数来通知线程池应该在何时调用我们的函数: PTP_TIMER CreateThreadpoolTimer( PTP_TIMER_CALLBACK pfnTimerCallback, PVOID pvContext, PTP_CALLBACK_ENVIRON pcbe ) 当我们想要向线程池注册计数器的时候,应该调用SetThreadpoolTimer IsThreadpoolTimerSet可以确定某个计时器是否已经被设置 引自 windows线程池 情形3,在内核对象触发时调用一个函数
许多应用程序创建线程的目的仅仅是为了等待一个内核对象被触发。一旦对象被触发,等待的线程会向另一个线程发出某种形式的通知并进入下一轮循环,等待该对象再次被触发。 如果想要注册一个工作项,让它在一个内核对象被触发的时候执行,那么我们需要一个原型函数: VOID CALLBACK WaitCallback( PTP_CALLBACK_INSTANCE pInstance, PVOID Context, PTP_WAIT Wait, TP_WAIT_RESULT WaitResult ) 然后通过调用CreateThreadpoolWait来创建一个线程池等待对象 当创建完成后,我们调用下面的函数来将一个内核对象绑定到这个线程池。 SetThreadpoolWait 线程池的内部会让一个线程调用WaitForMultipleObjects函数,传入通过SetThreadpoolWait函数注册的一组句柄,并传FALSE给bWaitAll参数。这样当任何一个句柄被触发的时候,线程池就会被唤醒。由于WaitForMulitipleObjects有一个限制,一次最多只能等待64个(MAXIMUM_WAIT_OBJECTS)句柄,因此线程池事实上正是为每64个内核对象分配一个线程进行等待,其效率还是相当高的。 引自 windows线程池 情形4:在异步I/O请求完成时调用一个函数
线程池函数可以替我们管理线程的创建和销毁,而这些线程会在内部等待I/O完成端口。但是,在打开一个文件或设备的时候,我们必须先将文件/设备与线程池的I/O完成端口关联起来。然后我们必须告诉线程池,当发往文件/设备的异步I/O请求完成时,应该调用哪个函数。 首先必须先编写符合以下原型的函数: VOID CALLBACK OverlappedCompletionRountine( PTP_CALLBACK_INSTANCE pInstance, PVOID pvContext, PVOID pOverlapped, ULONG IoResult, ULONG_PTR NumberOfBytesTransferred, PTP_IO pIo ); 当一个I/O操作完成的时候,这个函数会被调用并得到一个指向OVERLAPPED结构的指针,这个指针是我们在调用R/WriteFile来发出的I/O请求的时候传入的。操作的结果通过IoResult参数。 然后我们通过调用CreateThreadpoolIo来创建一个线程池I/O对象,并将我们想要与线程池内部的I/O完成端口相关联的文件/设备句柄(通过FILE_FLAG_OVERLAPPED标识调用CreateFile打开),在第一个参数中传入。 当线程池I/O对象创建完毕后,我们通过调用下面的函数来将嵌入在I/O项中的文件/设备与线程池内部的I/O完成端口关联起来: VOID StartThreadpoolIo 注意:每次在调用W/ReadFile之前,必须调用以上的函数,如果每次发出I/O请求之前没有调用StartThreadpoolIo,那么我们的verlappedCompletionRountine将不会被调用。 发出I/O请求之后,也可以取消,调用CancelThreadpoolIo 即使在发出请求的时候,W、ReadFile调用失败了,我们仍然必须调用CancelThreadpoolIo。 当对文件/设备的使用完成后,应该调用CloseHandle关闭,然后再调用CloseThreadpoolIo来解除它与线程池的关联。 还可以调用下面的函数来让另一个线程等待一个待处理的I/O请求完成: WaitForThreadpoolIoCallbacks 引自 windows线程池 回调函数的终止操作
线程池提供了一种便利的方法,用来描述在我们的回调函数返回之后,应该执行的一些操作。 LeaveCriticalSectionWhenCallbackReturns--------当回调函数返回的时候,线程池会自动调用LeaveCriticalSection,并在参数中传入指定的CRITICAL_SECTION结构。 ReleaseMutexWhenCallbackReturns-----当回调函数返回的时候,线程池会自动调用ReleaseMutex,并在参数中传入指定的HANDLE。 ReleaseSemaphoreWhenCallbackReturns------当回调函数返回的时候,线程池会自动调用eleaseSemaphore,并在参数中传入指定的HANDLE。 SetEventWhenCallbackReturns------当回调函数返回的时候,线程池会自动调用SetEvent,并在参数中传入指定的HANDLE。 FreeLibraryWhenCallbackReturns------当回调函数返回的时候,线程池会自动调用FreeLibrary,并在参数中传入指定的HMODULE。 引自 windows线程池 得体地销毁线程池:清理组
这小结描述的不是默认的线程池,这是因为它不会被销毁。默认的线程池的生命周期与进程相同,在进程终止的时候,windows会将其销毁并负责所有的清理工作。 引自 windows线程池
79人阅读
hao对本书的所有笔记 · · · · · ·
-
第196页 线程调度,优先级和关联性
windows在可调度的线程内核对象中选择一个,并将上次保存在线程上下文中的值载入CPU寄存器。...
-
第323页 同步设备I/O与异步设备I/O
I/O完成端口可以帮助我们创建高性能而且伸缩性好的APP,使用它可以让线程在读取设备和写入设...
-
第344页 windows线程池
-
第351页 纤程
使用纤程 纤程是在用户模式下实现的,内核对纤程一无所知,内核会根据我们定义的算法来对纤程...
-
第378页 windows内存体系结构
进程的虚拟地址空间 每个进程都有自己的虚拟地址空间,32位进程来说(就是编译出来的程序,而...
> 查看全部16篇
说明 · · · · · ·
表示其中内容是对原文的摘抄