andrew4582

Blocking Queue with BlockingCollection

Jan 6th, 2015
323
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 2.49 KB | None | 0 0
  1. using System;
  2. using System.Collections.Concurrent;
  3. using System.Collections.Generic;
  4. using System.Linq;
  5. using System.Text;
  6. using System.Threading;
  7. using System.Threading.Tasks;
  8.  
  9. namespace Common.Utilities
  10. {
  11.     /*
  12.     //example:
  13.     //countdown event to determine when the last worker is completed
  14.     CountdownEvent countdown = new CountdownEvent(4);
  15.  
  16.     using (var queue = new BlockingQueue(4))
  17.     {
  18.         for (int i = 0; i < actionsCount; i++)
  19.         {
  20.             int id = i;
  21.             queue.EnqueueTask(() =>
  22.             {
  23.                 Thread.Sleep(1000);
  24.                 return "Worker# " + id + " Finished";
  25.             }).ContinueWith(tsk =>
  26.             {
  27.                 if(!countdown.Signal())
  28.                     Console.WriteLine(tsk.Result);
  29.                 else
  30.                     Console.WriteLine("All completed");
  31.             });
  32.         }
  33.     }
  34.      */
  35.     public class BlockingQueue : IDisposable
  36.     {
  37.         readonly BlockingCollection<WorkItem> _taskQueue = new BlockingCollection<WorkItem>();
  38.  
  39.         public BlockingQueue(int workerCount)
  40.         {
  41.             // Create and start a separate Task for each consumer:
  42.             for (int i = 0; i < workerCount; i++)
  43.                 Task.Factory.StartNew(Consume);
  44.         }
  45.  
  46.         public void Dispose()
  47.         {
  48.             _taskQueue.CompleteAdding();
  49.         }
  50.  
  51.         public Task<object> EnqueueTask(Func<object> action, CancellationToken? cancelToken = null)
  52.         {
  53.             var tcs = new TaskCompletionSource<object>();
  54.             _taskQueue.Add(new WorkItem(tcs, action, cancelToken));
  55.             return tcs.Task;
  56.         }
  57.  
  58.         void Consume()
  59.         {
  60.             foreach (WorkItem workItem in _taskQueue.GetConsumingEnumerable())
  61.             {
  62.                 if (workItem.CancelToken.HasValue &&
  63.                     workItem.CancelToken.Value.IsCancellationRequested)
  64.                 {
  65.                     workItem.TaskSource.SetCanceled();
  66.                 }
  67.                 else
  68.                 {
  69.                     try
  70.                     {
  71.                         //call worker's action and set task source's result
  72.                         object result = workItem.Action();
  73.                         workItem.TaskSource.SetResult(result);
  74.                     }
  75.                     catch (OperationCanceledException ex)
  76.                     {
  77.                         if (ex.CancellationToken == workItem.CancelToken)
  78.                             workItem.TaskSource.SetCanceled();
  79.                         else
  80.                             workItem.TaskSource.SetException(ex);
  81.                     }
  82.                     catch (Exception ex)
  83.                     {
  84.                         workItem.TaskSource.SetException(ex);
  85.                     }
  86.                 }
  87.             }
  88.         }
  89.  
  90.         class WorkItem
  91.         {
  92.             public readonly TaskCompletionSource<object> TaskSource;
  93.             public readonly Func<object> Action;
  94.             public readonly CancellationToken? CancelToken;
  95.  
  96.             public WorkItem(TaskCompletionSource<object> taskSource, Func<object> action, CancellationToken? cancelToken)
  97.             {
  98.                 TaskSource = taskSource;
  99.                 Action = action;
  100.                 CancelToken = cancelToken;
  101.             }
  102.         }
  103.     }
  104. }
Advertisement
Add Comment
Please, Sign In to add comment