public void ConcurrencyQueueTester(IListeningQueue <string> q, int machineCount, int threadCount, int messagesPerThread) { int runCount = 0; int sentCount = 0; var actionerList = new List <QueueActioner <string> >(threadCount); var counter = new CountdownEvent(threadCount * messagesPerThread); try { for (int i = 0; i < machineCount; i++) { var actioner = new QueueActioner <string>(q, (s) => { counter.Signal( ); Interlocked.Increment(ref runCount); }, threadCount); actionerList.Add(actioner); actioner.Start( ); Thread.Sleep(500); } for (int i = 0; i < messagesPerThread * threadCount; i++) { q.Enqueue(""); sentCount++; } counter.Wait( ); foreach (var actioner in actionerList) { actioner.Stop(1000); } if (runCount != sentCount) { Debugger.Launch( ); } Assert.That(runCount, Is.EqualTo(sentCount)); } finally { Debug.WriteLine($"SendCount: {sentCount} - RunCount: {runCount} - Counter: {counter.CurrentCount}"); foreach (var actioner in actionerList) { actioner.Dispose(); } } }
/// <summary> /// Create an actioner for the given queue /// </summary> /// <param name="queue">The queue to run the action on</param> /// <param name="action">The action to perform</param> /// <param name="maxConcurrency">The maximum concurrency.</param> public QueueActioner(IListeningQueue <T> queue, Action <T> action, int maxConcurrency) { Queue = queue; Action = action; MaxConcurrency = maxConcurrency; _semaphore = new Semaphore(maxConcurrency, maxConcurrency); State = ActionerState.Stopped; WaitForQueueEvent = new AutoResetEvent(false); WaitForTaskEvent = new AutoResetEvent(false); RunningTasks = new ConcurrentDictionary <Task, byte>( ); queue.EnqueuedReceived += Queue_EnqueuedReceived; }