2010-12-01 109 views
3

在一個線程「A」,我想讀一個很長的文件,如出現這種情況,我想送讀取到另一個線程「B」的每個新線,他們會做一些事情。C# - 從一個線程實時文本進到另一個

基本上,我不想等待文件加載完成,然後我開始處理線。 (我絕對想要2線程和他們之間的溝通;我從來沒有這樣做過,我想學習)

那麼,我該怎麼做呢? 在線程A向線程B發送另一行之前,線程A應該等待線程B完成處理「當前線路」。但那樣做效率不高;因此,如何在線程B?緩衝區(抓線)

另外,請給的什麼方法我都用這個橫紗溝通,因爲我還沒有發現/看到任何有用的實例的實例。

謝謝。

回答

4

首先,目前還不清楚這兩個線程必定會有幫助。一次讀取一行的單個線程(這對於StreamReader來說非常簡單),並且在處理每行時可能至少執行一次。文件讀取被緩衝,操作系統可以在請求數據的代碼之前讀取,在這種情況下,大部分讀取操作可能會立即完成,因爲下一行已被操作系統預先從磁盤讀取,或者兩個線程都會必須等待,因爲數據不在磁盤上。 (具有2個線程坐着等待磁盤不會使事情更快的發展比有1個線程坐着等)。唯一可能的好處是,你避免死時間獲得下讀正在進行處理完前一之前,但是操作系統在任何情況下都會爲你做這件事。所以多線程的好處在這裏最好不過了。

但是,既然你說你這樣做是作爲一個學習鍛鍊,這可能不是一個問題...

我會使用一個BlockingCollection<string>的機制來從一個線程將數據傳遞到另一個。 (只要你使用的是.NET 4或更高版本,如果不是的話......我建議你轉到.NET 4--它將大大簡化這項任務。)你將從文件中讀取一行並將其放入從一個線程的集合:

string nextLine = myFileReader.ReadLine(); 
myBlockingCollection.Add(nextLine); 

然後其他線程可以從檢索行:

while (true) 
{ 
    string lineToProcess = myBlockingCollection.Take(); 
    ProcessLine(lineToProcess); 
} 

那會一樣快盤將讓我們通過文件讀線程運行它,而處理線程以任何速度處理數據。 Take方法只是簡單地坐在並等待處理線程超前於文件讀取線程。

這樣做的一個問題是,如果文件很大並且處理速度很慢,那麼您的閱讀線程可能會先行一步 - 您的程序可能會嘗試從文件中讀取千兆字節的數據,而只處理前幾千字節。在處理它之前沒有太多的點閱讀數據方式 - 你真的只想提前閱讀一點。您可以使用BlockingCollection<T>BoundedCapacity財產掐死的東西 - 如果你設置一些號碼,然後調用Add將阻止如果集合已經具有數在這行,你的讀線程將不會進行,直到處理循環處理其下一行。

將使用雙線程技術的程序的性能與簡單地從文件中讀取行並在單個線程中循環處理它們的程序進行性能對比將會很有趣。您將能夠看到從多線程方法中獲得的好處(如果有的話)。順便說一句,如果你的處理是非常CPU佔用的,你可以使用這個主題的變體來擁有多個處理線程(並且仍然是單個文件讀取線程),因爲BlockingCollection<T>非常樂意讓衆多消費者全部讀出的集合。當然,如果你完成處理文件行的順序很重要,那不會是一種選擇,因爲儘管你會以正確的順序開始處理,但如果你有多個處理線程,那麼有可能一個線程可能超過另一個,導致無序完成。

+0

謝謝伊恩。我從來沒有想過將文件讀取視爲緩衝。 (儘管我很清楚java中所謂的BUFFEREDReader)。但的確,我想這是一個練習。此外,它有助於獲得閱讀線程,因爲除了將線路發送到處理線程外,它還將動態地填充文本框。因此,在處理完成之前,文本框將已滿。我使用.NET 4,我會嘗試你的建議。處理不應該花費足夠長的時間來需要`BoundedCapacity`。再次感謝。 – Spectraljump 2010-12-01 17:20:11