我有一个Web服务,我需要抓取一堆记录并对每个记录进行一些处理。这个处理每行可能很长,我以线程方式运行这部分代码,将行的数据作为参数传递给函数。我可以处理1000行或更多行,并且我将数据处理线程的数量限制为10个。
要监视我的线程,我有一个Thread对象数组。
Dim RowThread(9) As Thread
在我生成一个新线程之前,在我的主线程(一个Web服务WebMethod)上,我循环遍历这个数组并查找我的下一个“可用”线程。
Dim avail_thread As Integer = -1
While avail_thread < 0
For t As Integer = 0 To THREADCOUNT - 1
If IsNothing(RowThread(t)) OrElse Not RowThread(t).IsAlive Then
avail_thread = t
Exit For
End If
Next
End While
...
RowThread(avail_thread) = New Thread(New ParameterizedThreadStart(AddressOf ProcessRow))
...
RowThread(avail_thread).Start(row)
正如您所看到的,它等待一个线程完成并将在下一个可用线程上生成下一行。如果所有10个线程都在使用中,它将继续循环并等到一个因为可用。
这种方法效果很好,并且在大多数服务器上运行良好。除了最近在某些服务器上,我注意到这会导致问题,因为它在此循环中将CPU固定。这会影响整体性能,因为我的主线程浪费了大量的CPU周期。为了简化这一点,我尝试了线程Sleep()甚至DoEvents(),但这些方法只会进一步降低性能。
还有其他人遇到过这种情况吗?我真的不认为我可以使用委托等等。因为这是在Web服务中,我不希望我的主调用结束,因为我不希望在处理完所有行之前发送结果。与ThreadPool相同的问题,更不用说ThreadPool会给你尽可能多的控制权。
如何负责生成然后从Web服务中管理线程?有没有办法执行非阻塞手动线程监控?
答案 0 :(得分:2)
为什么不将所有工作发布到线程池?它将以完美正确和有效的方式为您完成所有这些工作。它将创建正确数量的线程并在它们之间分配工作项。当您使用TPL的Task类时,您甚至可以监视任务完成情况。
答案 1 :(得分:0)
我想我在WaitHandle找到了答案。在我以前的研究中,我认为只能将它们与ThreadPool一起使用,但事实证明你可以将它们与手动启动的线程一起使用。
我现在用:
RowEvents(avail_thread) = New ManualResetEvent(False)
然后稍后将其作为我的参数对象的一部分传递给线程Start。当该函数完成时,我在该线程的ManualResetEvent对象上执行Set()。
我现在找到下一个可用的线程代码如下:
Dim avail_thread As Integer = -1
While avail_thread < 0
For t As Integer = 0 To THREADCOUNT - 1
If IsNothing(RowThread(t)) OrElse Not RowThread(t).IsAlive Then
avail_thread = t
Exit For
End If
Next
'All threads busy, call blocking wait
If avail_thread < 0 Then avail_thread = WaitHandle.WaitAny(RowEvents)
End While
这将在第一遍传递所有10个线程。如果它们都在运行,那么我调用WaitAny方法,当任何线程完成时返回焦点并将我的avail_thread变量设置为完成的索引线程