2012-09-17 39 views
3

对于Windows服务中的工作线程使用任务还是我们应该更好地使用Thread.Start()?如果大多数情况下处于闲置状态,那么可能甚至不会启动LongRunning,而是由FileSystemWatcher Events触发并使用Take()关闭BlockingCollections进行处理。是否可以使用Windows服务工作人员的任务

Public Class FileWatcherService 
Private _watchPaths As New List(Of String) From {"x:\Dir1","x:\Dir2","y:\Dir1", ...} 
Private _workers As New List(Of Task) 
Private _cancellationTokenSource As New CancellationTokenSource() 
Private _cancellationToken As CancellationToken = _cancellationTokenSource.Token 

Protected Overrides Sub OnStart(ByVal args() As String) 
    For Each path In _watchPaths 
     _workers.Add(
      Task.Factory.StartNew(
       Sub() 
        Dim fileProcessor As New FileProcessor 
        fileProcessor.StartWorking(path, _cancellationToken) 
       End Sub, TaskCreationOptions.LongRunning, _cancellationToken)) 
    Next 
End Sub 

Protected Overrides Sub OnStop() 
    _cancellationTokenSource.Cancel() 
    Task.WaitAll(_workers.ToArray) 
End Sub 
End Class 

Class FileProcessor 
Private _newFiles As New BlockingCollection(Of String) 
Sub _fileWatcher_Created(sender As Object, e As FileSystemEventArgs) 
    _newFiles.Add(e.FullPath, _cancellationToken) 
End Sub 

Async Function ProcessNewFiles() As Task 
    Do 
     Await ProcessFile(_newFiles.Take(_cancellationToken)) 
    Loop 
End Function 
End Class 

编辑

的方法上面没有空闲的时候释放工作线程,因为拿块()。 以下解决方案使用ActionBlock而不是BlockingCollection。此解决方案不会消耗线程,而会空闲地观看新文件。我旋转线程来处理新文件并在完成时释放它们。而且我不再使用LongRunning启动顶级工作任务。

Class FileProcessor 
Private _newFilesActionBlock As New ActionBlock(Of String)(
    Async Function(filePath) 
     Await ProcessFile(filePath) 
    End Function, 
     New ExecutionDataflowBlockOptions With { 
      .CancellationToken = _cancellationToken}) 

Sub _fileWatcher_Created(sender As Object, e As FileSystemEventArgs) 
         Handles __fileWatcher.Created 
    _newFilesActionBlock.Post(e.FullPath) 
End Sub 
'... 

末级

回答

2

TPL比欢迎除了.NET框架的更多。它使你的线程代码更容易处理,并且更具可读性。它允许你在不需要实例化和处理线程池和单独线程的情况下使你的Windows服务(或任何其他线程代码)成为多线程。

我在我的Windows服务中使用TPL,它对我很好,我大多数情况下建议使用TPL而不是经典线程池。

话虽这么说,有一些非常罕见的情况下,你仍然想自己处理的线程池,但基于您的代码段看来你并不真的需要与理会......

+0

我我特别感兴趣的是如何最好地创建这些顶级工作者(示例代码中的fileProcessor)。他们可能有百分之一,每个人永远活着,有些人大部分时间都处于闲置状态。如果我们将它们创建为LongRunning,它们将获得专用线程(使用目前的TPL实现,这在未来可能会发生变化)。如果我们在没有LongRunning的情况下创建它们,它们将在ThreadPool上创建,并且在闲置时不会消耗线程。 –

+0

我为我的问题添加了更好的解决方案。与专用工作线程相比,这种方法是否有意义? –

+0

有关此问题的更深入讨论[MSDN论坛](http://social.msdn.microsoft.com/Forums/en-US/parallelextensions/thread/1cecf738-686f-440f-ab8f-481402f13fa5) –

相关问题