[英]Can I convert while(true) loop to EventWaitHandle?
我試圖通過Parallel.ForEach
處理大量文本文件,將處理后的數據添加到BlockingCollection
。
問題是我希望Task
taskWriteMergedFile消耗集合並將它們至少每800000行寫入結果文件中。
我猜我無法在迭代中測試集合的大小,因為它是並行的,所以我創建了Task
。
在這種情況下,我可以將任務中的while(true)循環轉換為EventWaitHandle
嗎?
const int MAX_SIZE = 1000000;
static BlockingCollection<string> mergeData;
mergeData = new BlockingCollection<string>(new ConcurrentBag<string>(), MAX_SIZE);
string[] FilePaths = Directory.GetFiles("somepath");
var taskWriteMergedFile = new Task(() =>
{
while ( true )
{
if ( mergeData.Count > 800000)
{
String.Join(System.Environment.NewLine, mergeData.GetConsumingEnumerable());
//Write to file
}
Thread.Sleep(10000);
}
}, TaskCreationOptions.LongRunning);
taskWriteMergedFile.Start();
Parallel.ForEach(FilePaths, FilePath => AddToDataPool(FilePath));
mergeData.CompleteAdding();
您可能不想這樣做。 而是讓您的任務在收到文件時將每一行寫到文件中。 如果要將文件大小限制為80,000行,則在寫入第80,000行之后,關閉當前文件並打開一個新文件。
想一想,您無法使用的東西是因為GetConsumingEnumerable()
直到標記為添加完成才被停止。 將會發生的事情是,事情將進入睡眠循環,直到隊列中有80,000個項目,然后它將阻塞在String.Join
上,直到主線程調用CompleteAdding
為止。 有了足夠的數據,您將耗盡內存。
另外,除非您有充分的理由,否則不應在此處使用ConcurrentBag
。 只需對BlockingCollection
使用默認值,即ConcurrentQueue
。 ConcurrentBag
是一個相當特殊目的的數據結構,其性能不如ConcurrentQueue
。
因此,您的任務變為:
var taskWriteMergedFile = new Task(() =>
{
int recordCount = 0;
foreach (var line in mergeData.GetConsumingEnumerable())
{
outputFile.WriteLine(line);
++recordCount;
if (recordCount == 80,000)
{
// If you want to do something after 80,000 lines, do it here
// and then reset the record count
recordCount = 0;
}
}
}, TaskCreationOptions.LongRunning);
當然,這假定您已在其他位置打開了輸出文件。 最好在任務開始時打開輸出,並在退出foreach
之后將其關閉。
另一方面,您可能不希望生產者循環平行。 你有:
Parallel.ForEach(FilePaths, FilePath => AddToDataPool(FilePath));
我不確定AddToDataPool
在做什么,但是如果它正在讀取文件並將數據寫入集合中,則會遇到一些問題。 首先,磁盤驅動器一次只能執行一項操作,因此最終會讀取一個文件的一部分,然后讀取另一個文件的一部分,然后讀取另一個文件的一部分,依此類推。為了讀取下一個文件的每個塊,它必須尋找頭部到正確的位置。 磁盤磁頭搜索的成本非常高--5毫秒或更長。 CPU時間的永恆。 除非您執行的重負荷處理比讀取文件要花費更長的時間,否則最好總是一次處理一個文件。 除非您可以保證輸入文件位於單獨的物理磁盤上。 。 。
第二個潛在的問題是,在運行多個線程的情況下,您不能保證將事物寫入集合的順序。 當然,這可能不成問題,但是如果您希望將單個文件中的所有數據歸類到輸出中,則不會發生多個線程,每個線程向集合寫入多行。
只是要記住一點。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.