2012-09-17 103 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) –

相關問題