2011-06-16 74 views
0

我有一個VB.net項目,它使用後臺工作人員來做一些事情。如何在VB.net中動態創建後臺工作

現在我想擴大該項目能夠做多的東西:)

用戶可在文本框中輸入一個URL,當在解析按鈕,該程序的用戶點擊創建一個新的tabcontrol一個輸出一些數據。

我使用硬編碼的背景工作。

但現在我想運行多個後臺工作人員來做這些事情,所以我不能依靠硬編碼後臺工作人員。

是否可以動態創建後臺工作人員。

我沒有任何想法如何,因爲我覺得我需要設置不同的方法和變量一樣進行設置:

Private bw As BackgroundWorker = New BackgroundWorker 
bw.WorkerReportsProgress = True 
bw.WorkerSupportsCancellation = True 
AddHandler bw.DoWork, AddressOf bw_DoWork 
AddHandler bw.ProgressChanged, AddressOf bw_ProgressChanged 
AddHandler bw.RunWorkerCompleted, AddressOf bw_RunWorkerCompleted 
bw.RunWorkerAsync() 

Private Sub bw_DoWork()Private Sub bw_RunWorkerCompleted()Private Sub bw_ProgressChanged()

我想我需要在變量(list/dictionary)的某種數組中聲明後臺工作人員?除此之外,我不知道如何解決這個問題。

回答

6

儘管BackgroundWorkers可以成爲多線程的最佳,最簡單和最智能的方式,但有時候我會考慮使用其他方式之一來實現多線程。

關於哪種方法最適合在各種情況下使用,有很多爭論/爭論/搗鼓,所以我建議你可以快速瀏覽以下文章並自行決定(或者如果可以的話沒有找到足夠的資源做出決定,當然要問這個問題)。

你已經明顯地看過後面的地面工作人員,所以我不會列出他們,我也不會列出全部你可以線程的方式,只是你可能感興趣的一對夫婦。

首先,請查看ThreadPool。它很容易使用,並且很好地利用了回收/再利用資源。有一些缺點,如使用/持有太多的線程池可以exhuast池,但在簡單的應用程序不應該是一個問題。

還有CLR Async model這是支持跨框架本身的驚人數量,特別是在涉及某種形式的IO資源(文件,網絡等)的情況下。

另一種方法是Parallel Class,這是我的最愛之一 - 自從引入多線lambda以來,我一直都很喜歡它,併爲這樣做提供了一個很好的平臺。

在上述所有情況下,您可以即時創建三級線程,而無需自己創建和維護一組後臺工作人員。很難說從提供的信息中哪種方法最適合你,但是我個人認爲,如果檢索數據來填充標籤不會花太長時間,那麼我會考慮使用線程池。

希望有幫助!

+0

的Parallel.For和Parallel.ForEach是令人難以置信* *簡單的方式來獲得多線程工作在很多簡單的情況下,我堅持下去貫穿其中,並努力實現它們幾乎爲零。我在VB 2013上使用它們。我認爲SyncLock語句是VB專有的,並且相對於其他鎖定實現更加簡化了代碼。 – evilspoons 2015-07-10 18:52:29

+0

@evilspoons如果我沒有記錯,'SyncLock'在c#中轉換爲'lock'(https://msdn.microsoft.com/en-us/library/c5kehkcz.aspx) – Smudge202 2015-07-14 07:42:52

1

如果我明白你的問題的話,試着在類級別聲明BackgroundWorker爲:

Friend WithEvents bgw1 As BackgroundWorker 

然後在類的構造函數實例化。

Public Sub New() 
    bgw1 = New BackgroundWorker 
End Sub 

在類級別宣言選擇bgw1和事件下拉部分選擇DoWorkProgressChangedRunWorkerCompleted活動。

+0

tnx @Neolisk用於編輯。 – peyman 2015-10-17 15:02:47

9

這裏是如何

Public Class Form 
    Private Workers() As BackgroundWorker 
    Private NumWorkers = 0 

    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click 
     NumWorkers = NumWorkers + 1 
     ReDim Workers(NumWorkers) 
     Workers(NumWorkers) = New BackgroundWorker 
     Workers(NumWorkers).WorkerReportsProgress = True 
     Workers(NumWorkers).WorkerSupportsCancellation = True 
     AddHandler Workers(NumWorkers).DoWork, AddressOf WorkerDoWork 
     AddHandler Workers(NumWorkers).ProgressChanged, AddressOf WorkerProgressChanged 
     AddHandler Workers(NumWorkers).RunWorkerCompleted, AddressOf WorkerCompleted 
     Workers(NumWorkers).RunWorkerAsync() 
    End Sub 

End Class 

然後處理

Private Sub WorkerDoWork(sender As Object, e As System.ComponentModel.DoWorkEventArgs) 
    ' Do some work 
End Sub 

Private Sub WorkerProgressChanged(sender As Object, e As System.ComponentModel.ProgressChangedEventArgs) 
    ' I did something! 
End Sub 

Private Sub WorkerCompleted(sender As Object, e As System.ComponentModel.RunWorkerCompletedEventArgs) 
    ' I'm done! 
End Sub 

想象的多線程也可以這麼簡單。除非你有1000名工人,否則這很有效。在每個處理程序中的發件人參數可以用來檢查哪個工人報告進展情況等。

+0

如果我錯了,請糾正我,但是'ReDim'關鍵字不會創建一個新數組並將其分配給'Workers'?根據我的知識和'ReDim'以前的經驗,每次點擊按鈕時,數組將被銷燬,重新創建新的維度,然後新的後臺工作人員將被分配到最後一個元素,並且'工作人員'數組將不包含任何以前創建的背景工作人員。如果你想保留所有這些,你不應該使用'ReDim保護工人(NumWorkers)'? – RianBattle 2015-04-09 14:27:12

+0

如果你有這個代碼,並想停止CancelAsync(),你會怎麼做? 我正在尋找在一個類中使用這段代碼,以便我可以在我的程序中複製它,而不必重寫它。但我現在唯一掙扎的部分是我不能'停止'工人。 如果我按下按鈕兩次而沒有第一個叫做工人完成,我有兩個工作人員在做同樣的事情。我想在開始第二名之前取消第一名工作人員。 – nora 2016-05-17 15:50:16