Parallel.cs 2.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273
  1. using System;
  2. using System.Collections;
  3. using System.Collections.Generic;
  4. using System.Text;
  5. using System.Threading;
  6. namespace Utilities
  7. {
  8. public delegate void ForDelegate(int i);
  9. public delegate void DelegateProcess();
  10. // Based on:
  11. // http://coding-time.blogspot.pt/2008/03/implement-your-own-parallelfor-in-c.html
  12. // C# 2.0 adaptation based on:
  13. // http://dotnetgalactics.wordpress.com/2009/11/19/how-to-provide-a-parallel-for-loop-in-c2-0-2/
  14. public class Parallel
  15. {
  16. /// <summary>
  17. /// Parallel for loop. Invokes given action, passing arguments
  18. /// fromInclusive - toExclusive on multiple threads.
  19. /// Returns when loop finished.
  20. /// </summary>
  21. public static void For(int fromInclusive, int toExclusive, ForDelegate forDelegate)
  22. {
  23. // chunkSize = 1 makes items to be processed in order.
  24. // Bigger chunk size should reduce lock waiting time and thus
  25. // increase paralelism.
  26. int chunkSize = 4;
  27. // number of process() threads
  28. int threadCount = Environment.ProcessorCount;
  29. int index = fromInclusive - chunkSize;
  30. // locker object shared by all the process() delegates
  31. object locker = new object();
  32. // processing function
  33. // takes next chunk and processes it using action
  34. DelegateProcess process = delegate()
  35. {
  36. while (true)
  37. {
  38. int chunkStart = 0;
  39. lock (locker)
  40. {
  41. // take next chunk
  42. index += chunkSize;
  43. chunkStart = index;
  44. }
  45. // process the chunk
  46. // (another thread is processing another chunk
  47. // so the real order of items will be out-of-order)
  48. for (int i = chunkStart; i < chunkStart + chunkSize; i++)
  49. {
  50. if (i >= toExclusive) return;
  51. forDelegate(i);
  52. }
  53. }
  54. };
  55. // launch process() threads
  56. IAsyncResult[] asyncResults = new IAsyncResult[threadCount];
  57. for (int i = 0; i < threadCount; ++i)
  58. {
  59. asyncResults[i] = process.BeginInvoke(null, null);
  60. }
  61. // wait for all threads to complete
  62. for (int i = 0; i < threadCount; ++i)
  63. {
  64. process.EndInvoke(asyncResults[i]);
  65. }
  66. }
  67. }
  68. }