上一回提到了 BlockingCollection,順便提一個值得玩玩的事。
BlockingCollection 實作了IProducerConsumerCollection<T>. 此 interface 定義了製造者/消費者使用方式的安全執行緒集合。而BlockingCollection 是其中最典型的實作。BlockingCollection 可以使用GetConsumingEnumerable 取得加入/移除到集合中的項目。如下範例。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;
using System.Threading.Tasks;
using System.Collections.Concurrent;
using System.Threading;
namespace TPL_1 {
class Program {
static void Main(string[] args) {
var primes = new BlockingCollection<int>();
var t = Task.Factory.StartNew(
() =>
{
//取得對BlockingCollection中新增或移除的每個項目
foreach (var item in primes.GetConsumingEnumerable())
Console.WriteLine(item);
});
for (int i = 0; i < 5000000; i++)
if (IsPrime(i)) primes.Add(i);
primes.CompleteAdding(); //結束新增
t.Wait(); //直到 t 執行完
}
/// <summary>
/// 是否為質數
/// </summary>
/// <param name="input"></param>
/// <returns></returns>
static bool IsPrime(int input) {
int bound = (int)Math.Sqrt(input);
for (int i = 2; i <= bound; i++)
{
if (input % i == 0) return false;
}
return true;
}
static TimeSpan Time(Action a) {
Stopwatch w = Stopwatch.StartNew();
a();
return w.Elapsed;
}
}
}
執行起來,功能平凡無奇。好玩的是,這樣的技巧已經在之前的「讀取大型文字檔」中顯示過了,而GetConsumingEnumerable 以相同的方式實作出來。
CompleteAdding() 方法標示該集合不會再新增項目,因此 GetConsumingenumerable 的巡覽才會結束。
沒有留言:
張貼留言