static void Run <T>(IEnumerable <IndexedValue <T> > items, DegreeOfParallelism degreeOfParallelism, CancellationToken cancellationToken = default) { IOrderedQueue <IndexedValue <T> > orderedQueue = new LockFreeOrderedQueue <IndexedValue <T> >((x, y) => x.Index.CompareTo(y.Index)); var enqueuingCompleted = false; using var consumerLinkedCancellationTokenSource = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken); using var producersLinkedCancellationTokenSource = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken); var queueWorker = new Thread(() => { try { HandleOrderedQueue(orderedQueue, () => enqueuingCompleted, producersLinkedCancellationTokenSource.Token); } catch (OperationCanceledException) { // ignore this one } catch (Exception) { consumerLinkedCancellationTokenSource.Cancel(); } }); queueWorker.Start(); var encodingExceptions = ParallelExecution.ForEach( items, handleItem: item => { // if (item.Index == 27) { throw new Exception("!!!ParallelExecution!!!T_T"); } Console.WriteLine($"{Thread.CurrentThread.Name}: starts working on item {item.Index}"); // emulate encoding work Thread.Sleep(300); // * (item.Index % 2 == 0 ? 4 : 1)); // Console.WriteLine($"{Thread.CurrentThread.Name}: ends working on item {item.Index}"); orderedQueue.Enqueue(item); Semaphore.Release(); }, degreeOfParallelism, consumerLinkedCancellationTokenSource.Token); enqueuingCompleted = true; if (encodingExceptions.Count > 0) { if (!encodingExceptions.OfType <OperationCanceledException>().Any()) { producersLinkedCancellationTokenSource.Cancel(); } LogEncodingExceptions(encodingExceptions); } queueWorker.Join(); }
static void Main(string[] args) { // new CollectionDemo().ApiTest(); var degreeOfParallelism = new DegreeOfParallelism(3); //Environment.ProcessorCount - 2); // MainThread + QueueWorkerThread Console.WriteLine($"The number of processors on this computer is {Environment.ProcessorCount}."); Console.WriteLine($"The number of parallel workers is {degreeOfParallelism.Value}."); // var sourceFilepath = "./TestFiles/bigfile"; // var chunkOfBytes = FileUtils.ReadBytes(sourceFilepath, 16 * NumberOfBytesIn.MEGABYTE); using var cancellationTokenSource = new CancellationTokenSource(); void ConsoleCancelKeyPress(object sender, ConsoleCancelEventArgs args) { if (args.SpecialKey != ConsoleSpecialKey.ControlC) { return; } Console.WriteLine("Cancelling..."); args.Cancel = true; cancellationTokenSource.Cancel(); } Console.CancelKeyPress += ConsoleCancelKeyPress; var ranges = Enumerable.Range(0, 30) // Enumerable.Empty<int>() // .Union(Enumerable.Range(0, 2).OrderByDescending(i => i)) // .Union(Enumerable.Range(2, 2)) // .Union(Enumerable.Range(4, 26).OrderByDescending(i => i)) .ToList(); var items = ranges .Select((value, index) => { // if (index == 10) cancellationTokenSource.Cancel(); // emulate reading from disk Thread.Sleep(100); return(new IndexedValue <int>(index: value, value: index)); }); // .OrderByDescending(i => i.Index); // ParallelTests.TestCustom(items, degreeOfParallelism); // Console.WriteLine(); // ParallelTests.TestTpl(items); Run(items, degreeOfParallelism, cancellationTokenSource.Token); }
public static void TestCustom <T>(IEnumerable <IndexedValue <T> > items, DegreeOfParallelism degreeOfParallelism) { Console.WriteLine("Start testing Custom"); var sw = Stopwatch.StartNew(); ParallelExecution.ForEach(items, item => { Console.WriteLine($"{Thread.CurrentThread.Name} : takes item {item.Index}"); Thread.Sleep(200); }, degreeOfParallelism); sw.Stop(); Console.WriteLine("End testing Custom"); Console.WriteLine($"ms: {sw.ElapsedMilliseconds}, ticks: {sw.ElapsedTicks}"); }