2012-02-08 30 views
0

我有一个Web服务,我需要抓住一堆记录并对每个记录进行一些处理。这种处理可能每行都很冗长,我以线程方式运行这部分代码,将行数据作为参数传递给函数。我可以有1000或更多的行来处理,并且我将数据处理线程的数量限制为10.如何产生线程并在Web服务中管理?

为了监视我的线程,我有一个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

您使用的是什么版本的.NET?如果使用.NET 4.0,则应该尝试使用Parallel.ForEach。 – 2012-02-08 19:29:33

回答

2

为什么不把所有的工作都发布到线程池?它将以完全正确和有效的方式为您做到这一切。它会创建适当数量的线程并在其中分配工作项目。当你使用TPL的Task类时,你甚至可以监视任务完成。

+0

我想过使用线程池,但是我可以从字面上加载1000+个请求吗?我正在阅读的数据来自数据库,并将该行的数据传递给每个线程。排队时,1000行以上的数据位于哪里?可能是内存,如果我正在用BLOB等处理数据,那么我不想用完。 – nullvalue 2012-02-08 18:45:20

0

我想我在WaitHandle中找到了答案。在我之前的研究中,我认为只能将这些与ThreadPool一起使用,但事实证明,您也可以将它们与手动启动的线程一起使用。

我现在使用:

RowEvents(avail_thread) = New ManualResetEvent(False) 

后来在通过这个上线开始我的参数对象的一部分。当该函数完成时,我为该线程的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变量设置为已完成的索引线程时返回。