用隊列來處理訂單以及集合間性能比較
數組的大小是固定的,如果元素個數是動態的,就應使用集合類,集合可以根據集合類實現的接口組合為列表、集合和字典,集合實現的常用接口有如下
(1)IEnumerable<T>:如果將foreach語句用於集合,就需要IEnumerable接口,這個接口定義了方法GetEnumerator(),它返回了一個實現了IEnumerator接口的枚舉
(2)ICollection<T>:ICollection<T>接口由泛型集合類實現,使用這個接口可以獲得集合中的元素個數(Count屬性),把集合復制到數組中的方法(CopyTo()),還可以從集合中增加刪除元素(Add(),Remove(),Clear())
(3)IList<T>:IList<T>接口用於可通過位置訪問其中的元素列表,這個接口定義了一個索引器,可以在集合中的指定位置插入或則刪除某些項(Insert()和RemoveAt()方法)。IList<T>派生至ICollection<T>接口
(4)ISet<T>:ISet<T>接口由集實現,集允許合並不同的集,獲得兩個集的交集,檢查兩個集是否重疊。ISet<T>接口派生自ICollection<T>接口
(5)IDictionary<TKey,TValue>:IDictionary<TKey,TValue>接口由包含鍵和值泛型集合類實現,使用這個接口可以訪問所有的鍵和值,使用鍵類型的索引器可以訪問某些項,還可以添加和刪除某些項
隊列是其元素以先進先出(FIFO)的方式來處理的集合。先放入隊列中的元素會先讀取,其實就是我們在編程中遇到處理訂單的處理流程,先來的先處理,但如果考慮到不同訂單的優先級,我們會優先處理優先級高的訂單,先定義一個簡單訂單實體。
public class ProductOrder { public string Name { get;private set; } /// <summary> /// 用於標識訂單的優先級 /// </summary> public string Level { get; private set; } public string Content { get; private set; } public ProductOrder(string name, string level, string content) { this.Name = name; this.Level = level; this.Content = content; } public override string ToString() { return string.Format("Name:{0};Level{1};Content{2}",Name,Level,Content); } }
定義一個訂單處理核心類,用於處理改訂單,改類包含兩個不同的隊列用戶處理不同優先級的訂單,定義一個BackgroundWorker類來處理隊列中的訂單。
public class DealWithOrder { private BackgroundWorker Backwork; //用來控制工作線程 private bool isRunning = false; /// <summary> /// trigger this event when deal order /// </summary> public event Action<ProductOrder> ProgressShowEvent; private readonly Queue<ProductOrder> nomalQueue = new Queue<ProductOrder>(); private readonly Queue<ProductOrder> urgentQueue = new Queue<ProductOrder>(); public DealWithOrder(bool isdealOrder) { isRunning = isdealOrder; Backwork = new BackgroundWorker() { WorkerSupportsCancellation = true, WorkerReportsProgress = true }; Backwork.DoWork += Backwork_DoWork; Backwork.ProgressChanged += Backwork_ProgressChanged; } /// <summary> /// 開始工作線程 /// </summary> public void StartDealWithOrder() { Backwork.RunWorkerAsync(); } /// <summary> /// 沒處理完一個訂單觸發一次 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void Backwork_ProgressChanged(object sender, ProgressChangedEventArgs e) { if (!isRunning) return; switch (e.ProgressPercentage) { case 1: if (e.UserState is ProductOrder urgentOrder) ProgressShowEvent(urgentOrder); break; case 2: if (e.UserState is ProductOrder normalOrder) ProgressShowEvent(normalOrder); break; } } /// <summary> /// 工作線程處理訂單 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void Backwork_DoWork(object sender, DoWorkEventArgs e) { ProductOrder rec = null; while (isRunning) { lock (this) { if (urgentQueue.Count > 0) { rec = urgentQueue.Dequeue(); Backwork.ReportProgress(1, rec); } else { if (nomalQueue.Count > 0) { rec = nomalQueue.Dequeue(); Backwork.ReportProgress(2, rec); } } } } } /// <summary> /// 正常訂單的增加 /// </summary> /// <param name="nomalOrder"></param> public void AddNomalOrder(ProductOrder nomalOrder) { lock (this) { nomalQueue.Enqueue(nomalOrder); } } /// <summary> /// 緊急訂單的增加 /// </summary> /// <param name="urgentOrder"></param> public void AddUrgentOrder(ProductOrder urgentOrder) { lock (this) { urgentQueue.Enqueue(urgentOrder); } } /// <summary> /// 是否還有未處理完的正常訂單 /// </summary> public bool IsNomalAvailable { get { return nomalQueue.Count > 0; } } /// <summary> /// 是否還有未處理完的緊急訂單 /// </summary> public bool IsUrgentAvailable { get { return urgentQueue.Count > 0; } } }
在控制臺程序中添加訂單示例,並增加對ProgressShowEvent的訂閱
static void Main(string[] args) { var dealWithOrder = new DealWithOrder(true); dealWithOrder.ProgressShowEvent += DealWithOrder_ProgressShowEvent; var normalOrder = new ProductOrder("Simen", "nomal", "2222"); dealWithOrder.AddNomalOrder(normalOrder); var urgentOrder = new ProductOrder("Simen", "urgent", "1111"); dealWithOrder.AddUrgentOrder(urgentOrder); dealWithOrder.StartDealWithOrder(); Console.ReadKey(); } private static void DealWithOrder_ProgressShowEvent(ProductOrder obj) { Console.WriteLine(obj); }
輸出的結果如圖
完成示例應用程序中描述的任務的真實程序可以處理Web服務接收到的文檔,如果你不想用兩個隊列來實現不同優先級的訂單處理方式不一樣,可以考慮用鏈表來實現。
許多集合都提供了相同的功能,例如,SortedList類與SortedDictionary類的功能幾乎完全相同,但是其性能常常有很大區別,一個集合使用的內存少,另一個集合的元素檢索速度快,譬如說在List<int>每調用一次Add()方法都要移動整個集合,下圖顯示了各種集合在執行各種方法時所用的操作時間。
其中O(1)表示無論集合有多少項,這個操作所需要的時間不變
O(log n)表示操作所需要的時間隨集合集合中的元素增加而增加,但每個元素需要增加的時間不是線性的,而是成對稱曲線的
O(n)表示對於集合操作時間在最壞情況下是N
用隊列來處理訂單以及集合間性能比較