我刚刚实现了一个像这里描述的线程池
非常简单的实现,工作正常,但我的应用程序不再关闭。似乎两个工作线程(以及另一个线程,我猜是排队线程)卡在函数中
ntdll.ZwRemoveIoCompletion
我记得在QueueUserWorkItem的帮助条目(线程池实现中使用的WinAPI函数)中读过有关IO完成的内容,但我无法理解它。我使用WT_EXECUTELONGFUNCTION作为我的工作线程,因为执行可能需要一段时间,我想创建一个新的工作线程,而不是等待现有的线程完成。分配给工作线程的一些任务执行一些I / O操作。我尝试使用WT_EXECUTEINIOTHREAD,但它似乎没有帮助。
我应该提一下,主线程等待进入临界区,而调用堆栈是
System.Halt0, System.FinalizeUnits, Classes.Finalization, TThread.Destroy,
RtlEnterCriticalSection, RtlpWaitForCriticalSection
任何想法我在这里做错了什么?感谢您的帮助。
答案 0 :(得分:0)
要确保工作线程关闭,如果等待空IO完成端口,则需要通过某种方式唤醒它们。最简单的方法似乎是向端口发送某种类型的NULL消息 - 然后他们应该将其视为一种有序停止的信号。
答案 1 :(得分:0)
您必须先从关键部分离开,然后才能再次进入。所以问题在于锁定。
在某些帖子中:
EnterCriticalSection(SomeCriticalSection);
sort code...
LeaveCriticalSection(SomeCriticalSection);
在其他一些帖子中:
EnterCriticalSection(SomeCriticalSection);
clean up code...
LeaveCriticalSection(SomeCriticalSection);
如果排序代码在第一个线程中运行而第二个线程尝试运行清理代码,则第二个线程将等到排序代码完成并离开临界区。只有在离开临界区后,您才能进入相同的临界区。我希望这可以帮助您缩小死锁代码,因为它位于一个关键部分。
要获得完成端口句柄,您可以在创建完成端口时保存它的句柄:
FIoCPHandle := CreateIoCompletionPort(INVALID_HANDLE_VALUE, 0 , 0, FNumberOfConcurrentThreads);
答案 2 :(得分:0)
使用QueueUserWorkItem
时,只要工作线程已经返回到线程池,您就不必做任何事情来关闭它们。线程池的WT_EXECUTEDEFAULT
组件将工作项排队到I / O完成端口。此端口是线程池内部实现的一部分,无法访问。
您是否可以为看似卡住的线程提供更详细的调用堆栈?它会使这个问题更容易诊断。