上一回提到了 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 的巡覽才會結束。
沒有留言:
張貼留言