BlockingCollection удобно использовать для построения пайплайна обработки данных:
static void ProcessFile(string inputPath, string outputPath) { var inputLines = new BlockingCollection<string>(); var processedLines = new BlockingCollection<string>(); // Stage #1 var readLines = Task.Factory.StartNew(() => { try { foreach (var line in File.ReadLines(inputPath)) inputLines.Add(line); } finally { inputLines.CompleteAdding(); } }); // Stage #2 var processLines = Task.Factory.StartNew(() => { try { foreach(var line in inputLines.GetConsumingEnumerable() .Select(line => Regex.Replace(line, @"\s+", ", "))) { processedLines.Add(line); } } finally { processedLines.CompleteAdding(); } }); // Stage #3 var writeLines = Task.Factory.StartNew(() => { File.WriteAllLines(outputPath, processedLines.GetConsumingEnumerable()); }); Task.WaitAll(readLines, processLines, writeLines); }
Однако, BlockingCollection - это обертка над интерфейсом IProducerConsumerCollection, коий реализуют выше указанные Concurrent коллекции. Так вот мы активно используем BlockingCollection. И недавно выяснилось, что по умолчанию BlockingCollection использует ConcurrentQueue, то есть поддерживает порядок обработки данных. Что зачастую нам не требуется. ConcurrentBag же не поддерживает порядок, но, как вы уже догадались, работает быстрее.
В целом же разница исчисляется во многих разах:
For mixed producer-consumer scenarios that do not require item ordering, ConcurrentBag(T) can be dramatically more efficient than ConcurrentStack(T) , ConcurrentQueue(T), and other synchronized collections.
Подробнее со статистикой здесь:
Thread-safe Collections in .NET Framework 4 and Their Performance Characteristics
Комментариев нет:
Отправить комментарий