static void Main(string[] args) { // create a barrier Barrier barrier = new Barrier(2); // create a task that will complete Task.Factory.StartNew(() => { Console.WriteLine("Good task starting phase 0"); barrier.SignalAndWait(); Console.WriteLine("Good task starting phase 1"); barrier.SignalAndWait(); Console.WriteLine("Good task completed"); }); // create a task that will throw an exception // with a selective continuation that will reduce the // particpant count in the barrier Task.Factory.StartNew(() => { Console.WriteLine("Bad task 1 throwing exception"); throw new Exception(); }).ContinueWith(antecedent => { // reduce the particpant count Console.WriteLine("Reducing the barrier participant count"); barrier.RemoveParticipant(); }, TaskContinuationOptions.OnlyOnFaulted); // wait for input before exiting Console.WriteLine("Press enter to finish"); Console.ReadLine(); }
static int[] CalculationInTask(object p) { var p1 = p as Tuple <int, int, System.Threading.Barrier, List <string> >; System.Threading.Barrier barrier = p1.Item3; List <string> data = p1.Item4; int start = p1.Item1 * p1.Item2; int end = start + p1.Item2; Console.WriteLine("Задача {0}: раздел от {1} до {2}", Task.CurrentId, start, end); int[] charCount = new int[26]; for (int j = start; j < end; j++) { char c = data[j][0]; charCount[c - 97]++; } Console.WriteLine("Задача {0} завершила вычисление. {1} раз а, {2} раз z", Task.CurrentId, charCount[0], charCount[25]); barrier.RemoveParticipant(); Console.WriteLine("Задача {0} удалена; количество оставшихся участников: {1}", Task.CurrentId, barrier.ParticipantsRemaining); return(charCount); }
static void Main(string[] args) { var participants = 5; // We create a CancellationTokenSource to be able to initiate the cancellation var tokenSource = new CancellationTokenSource(); // We create a barrier object to use it for the rendez-vous points var barrier = new Barrier(participants, b => { Console.WriteLine("{0} paricipants are at rendez-vous point {1}.", b.ParticipantCount, b.CurrentPhaseNumber); }); for (int i = 0; i < participants; i++) { var localCopy = i; Task.Delay(1000 * localCopy + 1, tokenSource.Token) .ContinueWith(_ => { Console.WriteLine("Task {0} left point A!", localCopy); Thread.Sleep(1000 * localCopy + 1); // Do some "work" if (localCopy % 2 == 0) { Console.WriteLine("Task {0} arrived at point B!", localCopy); barrier.SignalAndWait(tokenSource.Token); } else { Console.WriteLine("Task {0} changed its mind and went back!", localCopy); barrier.RemoveParticipant(); return; } }, TaskContinuationOptions.NotOnCanceled) .ContinueWith(_ => { Thread.Sleep(1000 * localCopy + 1); Console.WriteLine("Task {0} arrived at point C!", localCopy); barrier.SignalAndWait(tokenSource.Token); }, TaskContinuationOptions.NotOnCanceled); } Console.WriteLine("Main thread is waiting for {0} tasks!", barrier.ParticipantsRemaining - 1); Console.WriteLine("Press enter to cancel!"); Console.ReadLine(); if (barrier.CurrentPhaseNumber < 2) { tokenSource.Cancel(); Console.WriteLine("We canceled the operation!"); } else { Console.WriteLine("Too late to cancel!"); } Console.WriteLine("Main thread is done!"); Console.ReadLine(); }
// static int[] CalculationInTask(object p) static int[] CalculationInTask(int jobNumber, int partitionSize, Barrier barrier, IList<string> coll) { var data = new List<string>(coll); int start = jobNumber * partitionSize; int end = start + partitionSize; Console.WriteLine("Task {0}: partition from {1} to {2}", Task.CurrentId, start, end); int[] charCount = new int[26]; for (int j = start; j < end; j++) { char c = data[j][0]; charCount[c - 97]++; } Console.WriteLine("Calculation completed from task {0}. {1} times a, {2} times z", Task.CurrentId, charCount[0], charCount[25]); barrier.RemoveParticipant(); Console.WriteLine("Task {0} removed from barrier, remaining participants {1}", Task.CurrentId, barrier.ParticipantsRemaining); return charCount; }
static void Main(string[] args) { var participants = 5; Barrier barrier = new Barrier(participants + 1, // We add one for the main thread. b => { Console.WriteLine("{0} paricipants are at rendez-vous point {1}.", b.ParticipantCount - 1, // We substract the main thread . b.CurrentPhaseNumber); }); for (int i = 0; i < participants; i++) { var localCopy = i; Task.Run(() => { Console.WriteLine("Task {0} left point A!", localCopy); Thread.Sleep(1000 * localCopy + 1); // Do some "work" if (localCopy % 2 == 0) { Console.WriteLine("Task {0} arrived at point B!", localCopy); barrier.SignalAndWait(); } else { Console.WriteLine("Task {0} changed its mind and went back!", localCopy); barrier.RemoveParticipant(); return; } Thread.Sleep(1000 * (participants - localCopy)); Console.WriteLine("Task {0} arrived at point C!", localCopy); barrier.SignalAndWait(); }); } Console.WriteLine("Main thread is waiting for {0} tasks!", barrier.ParticipantsRemaining - 1); barrier.SignalAndWait(); // Waiting at the first phase barrier.SignalAndWait(); // Waiting at the second phase Console.WriteLine("Main thread is done!"); }
private static void CalculationInTask(int jobNumber, int partitionSize, Barrier barrier, IList<string>[] coll, int loops, int[][] results) { LogBarrierInformation("CalculationInTask started", barrier); for (int i = 0; i < loops; i++) { var data = new List<string>(coll[i]); int start = jobNumber * partitionSize; int end = start + partitionSize; WriteLine($"Task {Task.CurrentId} in loop {i}: partition from {start} to {end}"); for (int j = start; j < end; j++) { char c = data[j][0]; results[i][c - 97]++; } WriteLine($"Calculation completed from task {Task.CurrentId} in loop {i}. " + $"{results[i][0]} times a, {results[i][25]} times z"); LogBarrierInformation("sending signal and wait for all", barrier); barrier.SignalAndWait(); LogBarrierInformation("waiting completed", barrier); } barrier.RemoveParticipant(); LogBarrierInformation("finished task, removed participant", barrier); }
public void _08_testPutTake_fixed() { TEST = false; // Test that the queue performs correctly under unpredictable concurrent access by using multiple threads to // to to perform Put and Take operations over a period of time and that nothing wnet wrong MMChannel mmMain = null; Console.WriteLine("\nStart of Test Run No. {0} in Test Suite No. {1}\n", ++initTestRunNumber, initTestSuiteNumber); try { int capacity = 500, fileSize = 1000000, viewSize = 1000; string QueueName = "_08_testPutTake_fixed"; // If only performing a small number of trials then GC could impact the timing tests so try and request it beforehand // In the case of a small number of trials, hopefully GC won't be required again before the end of the test System.GC.Collect(); // INFO Cannot use the Property (get/set) with an Interlocked - // Store the value of the computed checksums here using Interlocked to ensure atomicty long putSum = 0; // Start and end times of the test run long timerStartTime = 0, timerEndTime = 0; // test parameters // Performance nPairs = 10, capacity = 10, nTrials = 1,000,000 = BlockingCollection = 60s, MMQueue = 254s int nPairs = 10, nTrials = initNoOfTrials; Random rand = new Random(); // Create the MMChannel which will instantiate the memory mapped files, mutexes, semaphores etc ... mmMain = MMChannel.GetInstance(QueueName, fileSize, viewSize, capacity, TEST, initTestDataStructureType); #region Barrier and Barrier Action declaration // The barrier will wait for the test runner thread plus a producer and consumer each for the number of pairs // Waits for them all to be ready at the start line and again at the finish Barrier _barrier = new Barrier(nPairs + 1, actionDelegate => { // Check to see if the start time variable has been assigned or still = zero // If false then this is the first execution of the barrier action (at the start). Otherwise it is the // second execution 9at the finish) const long zeroFalse_1 = 0; // Not passed by ref so no need to be assignable bool started = Interlocked.Equals(timerStartTime, zeroFalse_1); started = !started; // Store the start time or the end time depending on which execution this is long t = DateTime.Now.Ticks; if (!started) { Interlocked.Exchange(ref timerStartTime, t); } else { Interlocked.Exchange(ref timerEndTime, t); } } ); #endregion Barrier and Barrier Action declaration // create pairs of threads to put and take items to/from the queue // Including the test runner thread the barriers will wait for nPairs * 2 + 1 ther for (int i = 0; i < nPairs; i++) { #region Producer Lamda declaration new Thread( new ThreadStart( // Old way - replace lamda expression '() =>' with 'delegate' () => { try { DateTime centuryBegin = new DateTime(2001, 1, 1); DateTime currentDate = DateTime.Now; int elapsedTicks = (int)(currentDate.Ticks - centuryBegin.Ticks); long result = 0; // Wait at the barrier (start line) until all test threads have been created and are ready to go _barrier.SignalAndWait(); // Put the data into the queue as Strings, generating a new random number each time // The consumer will convert back to integers and sum them // The Producer's sum should equal the Consumenr's sum at the end of the test for (int j = nTrials; j > 0; --j) { // If the RNG is sound then this proves that the data enqueued was dequeued int r = rand.Next(maxLongRandomSeed); _08_MMData data; // Test data string to enqueue and dequeue. Convert to a byte array. This array is a reference type so cannot be directly // passed to the View Accessor char[] encodedData = Convert.ToString(r).ToCharArray(); // Store the length of the array for dequeueing later data.TextLength = encodedData.Length; // Copy the data to unmanaged memory char by char for (int k = 0; k < data.TextLength; k++) { unsafe { data.Text[k] = encodedData[k]; } } mmMain.Put(data); result += r; } // Atomically store the computed checksum // Comment out for Test 01 as we have already incremented it Interlocked.Add(ref putSum, result); // Wait at the barrier (finish line) until all test threads have been finished _barrier.SignalAndWait(); } catch (Exception unexpected) { _barrier.RemoveParticipant(); Console.Write("Producer thread terminated after catching an exception from MMChannel 'put()'"); Console.Write(unexpected); } } )).Start(); #endregion Producer Lamda declaration } // Wait for all the threads to be ready _barrier.SignalAndWait(); // Wait for all the threads to finish _barrier.SignalAndWait(); // calculate the number of ticks elapsed during the test run long elapsedTime = Interlocked.Read(ref timerEndTime) - Interlocked.Read(ref timerStartTime); Console.WriteLine("Intermediate Result of _08_testPutTake_fixed() - elapsed time = {0} timer ticks for {1} producer/consumer pairs and {2} Messages", elapsedTime, nPairs, nTrials); // Calculate the number of ticks per item enqueued and dequeued - the throughput of the queue // A single tick represents one hundred nanoseconds or one ten-millionth of a second. // There are 10,000 ticks in a millisecond. long ticksPerItem = elapsedTime / (nPairs * (long)nTrials); TimeSpan elapsedSpan = new TimeSpan(ticksPerItem); double milliSeconds = elapsedSpan.TotalMilliseconds; long nanoSeconds = ticksPerItem * 100; long throughput = 1000000000 / nanoSeconds; // Compares the checksum values computed to determine if the data enqueued was exactly the data dequeued Console.WriteLine("1st Result of _08_testPutTake_fixed() = (data enqueued = {0} after {1} trials each by {2} pairs of producers/consumers", Interlocked.Read(ref putSum), nTrials, nPairs); Console.WriteLine("2nd Result of _08_testPutTake_fixed() = (Average latency = {0} timer ticks <= Threshold value {1}) = {2}", Interlocked.Read(ref ticksPerItem), AVERAGE_THROUGHPUT_THRESHOLD_TICKS, Interlocked.Read(ref ticksPerItem) <= AVERAGE_THROUGHPUT_THRESHOLD_TICKS); Console.WriteLine("_08_testPutTake_fixed Throughput = {0} messages per second ", throughput); Console.WriteLine("_08_testPutTake_fixed {0} timer ticks = {1} nanoseconds or {2} milliseconds", ticksPerItem, nanoSeconds, milliSeconds); Console.WriteLine("\nEnd of Test Run No. {0} in Test Suite No. {1}\n", initTestRunNumber, initTestSuiteNumber); } catch (Exception unexpected) { Console.Write(unexpected); throw; } finally { // Temporarily delay disposing the queue and its IPC artefacts to allow the consumers to finish draining the queue // This will be fixed by waiting in an interrupible loop for the mutex inside the queue and checking if shutdown // Thread.Sleep(1000); mmMain.Report(); mmMain.Dispose(); } }
private static bool RunBarrierTest7_Bug603035() { TestHarness.TestLog("*RunBarrierTest7_Bug603035"); bool failed = false; for (int j = 0; j < 100 && !failed; j++) { Barrier b = new Barrier(0); Action[] actions = Enumerable.Repeat((Action)(() => { for (int i = 0; i < 400; i++) { try { b.AddParticipant(); b.RemoveParticipant(); } catch { failed = true; break; } } }), 4).ToArray(); Parallel.Invoke(actions); if (b.ParticipantCount != 0) failed = true; } if (failed) { TestHarness.TestLog("Bug603035 failed"); return false; } TestHarness.TestLog("Bug603035 succeeded"); return true; }