2

我刚刚实现了一个如此处所述的线程池

Allen Bauer 谈线程池

非常简单的实现,工作正常,但我的应用程序不再关闭。似乎有两个工作线程(和另一个线程,我猜是排队线程)卡在函数中

ntdll.ZwRemoveIoCompletion

我记得在 QueueUserWorkItem(线程池实现中使用的 WinAPI 函数)的帮助条目中读过一些关于 IO 完成的内容,但我无法正确理解。我将 WT_EXECUTELONGFUNCTION 用于我的工作线程,因为执行可能需要一段时间,我希望创建一个新的工作线程而不是等待现有的工作线程完成。分配给工作线程的一些任务执行一些 I/O 工作。我尝试使用 WT_EXECUTEINIOTHREAD 但它似乎没有帮助。

我应该提到,主线程等待进入关键部分,调用堆栈为

System.Halt0, System.FinalizeUnits, Classes.Finalization, TThread.Destroy,
RtlEnterCriticalSection, RtlpWaitForCriticalSection

有什么想法我在这里做错了吗?提前感谢您的帮助。

4

3 回答 3

0

为了确保工作线程关闭,如果它们在空的 IO 完成端口上等待,您需要有某种方法来唤醒它们。最简单的方法似乎是向端口发布某种 NULL 消息 - 然后他们应该将此视为有序停止的信号。

于 2009-04-01T08:55:56.893 回答
0

您必须先离开临界区,然后才能再次进入。所以问题出在锁里面。

在某些线程中:

EnterCriticalSection(SomeCriticalSection);
sort code...
LeaveCriticalSection(SomeCriticalSection);

在其他一些线程中:

EnterCriticalSection(SomeCriticalSection);
clean up code...
LeaveCriticalSection(SomeCriticalSection);

如果排序代码在第一个线程中运行并且第二个线程尝试运行清理代码,则第二个线程将等待直到排序代码完成并且您离开临界区。只有离开临界区后,才能进入相同的临界区。我希望这将帮助您缩小死锁代码的范围,因为它位于关键部分内。

要获取完成端口句柄,您可以在创建完成端口时保存它的句柄:

FIoCPHandle := CreateIoCompletionPort(INVALID_HANDLE_VALUE, 0 , 0, FNumberOfConcurrentThreads);
于 2009-04-02T11:38:37.477 回答
0

使用QueueUserWorkItem时,只要工作线程已经返回到线程池,就不需要做任何事情来关闭它们。线程池的WT_EXECUTEDEFAULT组件将工作项排队到 I/O 完成端口。此端口是线程池内部实现的一部分,您无法访问。

您能否为似乎被卡住的线程提供一些更详细的调用堆栈?这将使这个问题更容易诊断。

于 2009-12-11T07:33:39.420 回答