SerailQueue.cs 1.9 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465
  1. using System;
  2. using System.Threading;
  3. using System.Collections.Generic;
  4. namespace EZXR.Glass.Core.Threading
  5. {
  6. public class SerailQueue
  7. {
  8. readonly object _locker = new object();
  9. Thread[] _workers;
  10. Queue<Action> _itemQ = new Queue<Action>();
  11. public SerailQueue(int workerCount)
  12. {
  13. _workers = new Thread[workerCount];
  14. // Create and start a separate thread for each worker
  15. for (int i = 0; i < workerCount; i++)
  16. (_workers[i] = new Thread(Consume)).Start();
  17. }
  18. public void Shutdown(bool waitForWorkers)
  19. {
  20. // Enqueue one null item per worker to make each exit.
  21. foreach (Thread worker in _workers)
  22. EnqueueItem(null);
  23. // Wait for workers to finish
  24. if (waitForWorkers)
  25. foreach (Thread worker in _workers)
  26. worker.Join();
  27. }
  28. public void EnqueueItem(Action item)
  29. {
  30. lock (_locker)
  31. {
  32. _itemQ.Enqueue(item); // We must pulse because we're
  33. Monitor.Pulse(_locker); // changing a blocking condition.
  34. }
  35. }
  36. public bool isBusy()
  37. {
  38. lock (_locker)
  39. {
  40. return _itemQ.Count > 0;
  41. }
  42. }
  43. void Consume()
  44. {
  45. while (true) // Keep consuming until
  46. { // told otherwise.
  47. Action item;
  48. lock (_locker)
  49. {
  50. while (_itemQ.Count == 0) Monitor.Wait(_locker);
  51. item = _itemQ.Dequeue();
  52. }
  53. if (item == null) return; // This signals our exit.
  54. item(); // Execute item.
  55. }
  56. }
  57. }
  58. }