2010-10-08 151 views
3

假設我想要做的是驗證一百萬個字符串,並且每個驗證需要幾秒鐘的時間。重新啓動正常的線程

我的方法:

我已經線程的數組聲明如下:

Thread[] workers = new Thread[50]; 

我不知道所有的字符串數組中,他們通過一些計算得到的,然後我不噸有所有的人,當我啓動這一進程,但我有一個返回下一個方法:

public string next() 
{ 
    //my code 
} 

我已經能夠運行所有的50個線程這樣的:

for (int x = 0; x < 50; x++) 
{ 
workers[x] = new Thread(new ParameterizedThreadStart(myMethod)); 
workers[x].Start(next()); 
} 

哪個迅速啓動所有50個線程「在同一時間」,然後我的日誌(由myMethod的餵養)獲得近50個反應在同一時間(1〜1.5秒)

如何獲得每一個剛剛完成的線程都考慮到Thread類沒有公開任何事件或類似的東西而再次運行下一個字符串?

注:我已經做了一些性能測試,我更喜歡使用常規線程而不是BackgroundWorkers。

在.net 3.5中使用C#。

+0

是否使用TPL通過Rx擴展選項?有非常容易的選擇... – 2010-10-08 19:54:06

+0

-1我不明白你的問題。大聲笑,只是開玩笑+1 – 2010-10-26 11:30:13

+0

@Ninja你有我想知道什麼是這個問題混淆了一會兒..哈哈 – Marcelo 2010-10-26 12:25:11

回答

5

這聽起來像你應該使用ThreadPool。然後,您可以只執行:

while(MoreWorkIsAvailable) 
{ 
    string nextString = next(); 
    ThreadPool.QueueUserWorkItem(new WaitCallback(myMethod), nextString); 
} 

線程池,甚至可以讓你把硬工資帽上的線程的最大數量,允許通過SetMaxThreads在某一時間運行。

+0

+1我從來沒有使用ThreadPool,但是如果這項工作是對問題的完美解決方案。 – Kendrick 2010-10-08 19:35:49

+0

難道這不會把我在內存中排列的一百萬個字符串放在隊列中嗎? – Marcelo 2010-10-08 19:50:03

+0

它會 - 如果你處理一百萬條目,它可能是矯枉過正的 - 在這種情況下,等待句柄可能是一個更好的選擇... – 2010-10-08 19:52:57

1

您可以像使用ADO.NET或枚舉一樣使用next()方法。保持返回值直到完成,然後返回null。讓你的線程在while循環中從方法中消耗,直到方法返回null,然後退出。

爲了澄清,有一些你需要做的背景工作。你必須讓你的next()方法是線程安全的,所以你總是返回下一個值而不重複。您還必須將引用傳遞給對象,而不是next()方法的輸出。線程安全的部分是它的唯一真正複雜的事情,它只是意味着你必須鎖定您的next()方法的一部分:

  • 確定下一個字符串值,使用
  • 和更新任何對象狀態

一旦狀態穩定,就可以釋放該鎖並且下一個線程可以獲取其字符串以進行工作。

編輯:雖然我喜歡簡單的ThreadPool方法,但這仍然可以走。在這種情況下,代碼將是這樣的:

YourStringGenerator generator; 
//instatiate generator 
for (int x = 0; x < 50; x++) 
{ 
    workers[x] = new Thread(new ParameterizedThreadStart(myMethod)); 
    workers[x].Start(generator); 
} 

然後

myMethod(YourStringGenerator generator) 
{ 
    String compare; 
    while((compare=generator.next())!=null) 
    { 
     //do comparison, etc. 
    } 
    return; 
} 

下一個()看起來像

String next() 
{ 
    lock(this.index) //see msdn for info. Link below. 
    { 
     //determine next string 
     //update index 
    } 
    //generate or get next string from list and return it 
    //or if empty, return null 
} 

see msdn for info

+0

@MarceloRamires:這是自我管理這個問題。你需要讓自己的線程方法獲取工作,這將導致同步問題發揮作用。這就是爲什麼ThreadPool在這些情況下更好... – 2010-10-08 19:32:23

+0

不,這段時間進入線程(即在myMethod())中。開始一個線程會有開銷,所以有一個適合您的處理器和問題的最佳線程數。爲每個比較產生一個新線程可能比在主線程中做得慢。 – Kendrick 2010-10-08 19:33:43

+0

您不應該在一段時間內啓動線程,而是在50個線程中的每一個線程上運行一段時間,直到仍然有一個字符串要處理,並由next()方法返回。 – treaschf 2010-10-08 19:34:48

2

你不能得到一個事件由線程系統。你可以用Thread.Join等待一個線程,但是你不能等待任何線程並獲得第一個完成的線程。您最好的方法是在每個線程中放置一個while循環,輪詢工作項的隊列,直到隊列爲空。

1

添加到你的線程方法不僅僅處理一塊數據,而是「下一個未聲明」的數據。

您將希望圍繞枚舉器的MoveNext進行一些同步,並將該引用的副本抓取到Current。沒有兩個線程能夠推進統計員並同時獲取物品。然後,一旦你有你的參考,釋放同步鎖定並做你的驗證。

您可能還想看看Microsoft的Px並行擴展,以利用多個CPU(核心?)。我沒有使用它,但如果您的驗證是純粹的算法(而不是針對數據庫進行檢查),多處理器參與是擊敗單線程模型的唯一方法。