public void MultipleAcquiresSemaphoreTest() { const int ACQUIRES = 10; bool[] acquires = new bool[ACQUIRES]; Thread[] threads = new Thread[ACQUIRES]; SafeSemaphore sem = new SafeSemaphore(10, 10); for (int i = 0; i < ACQUIRES; ++i) { threads[i] = new Thread((idx) => { bool res; do { res = sem.TryAcquire(1); }while (!res); acquires[(int)idx] = true; }); threads[i].Start(i); } // check if all threads terminate bool result = true; for (int i = 0; i < ACQUIRES; ++i) { bool partial = threads[i].Join(2000); if (!partial) { TerminateThread(threads[i]); } result = result && partial; } if (!result) { Assert.Fail("One or more threads not terminated!"); } // check if all results are true for (int i = 0; i < ACQUIRES; ++i) { if (!acquires[i]) { Assert.Fail("Unsuccessful acquire!"); } } Assert.AreEqual(false, sem.TryAcquire(1)); }
public void Ready() { if (_subscription == null) { throw new Exception("Subscription not initialized, call Init first"); } if (PriorityQueue == null) { throw new Exception("PriorityQueue not initialized, call Init first"); } lock (SyncRoot) { _pool = new SafeSemaphore(_watcher, BatchSize, BatchSize, _sharedSemaphore); } StartConsumerThread(string.Format("Consumer thread: {0}, Priority queue: {1}", ConsumerTag, _queuePriorirty)); }
/// <summary> /// Initialize an object of <see cref="BurrowConsumer"/> /// </summary> /// <param name="channel">RabbitMQ.Client channel</param> /// <param name="messageHandler">An instance of message handler to handle the message from queue</param> /// <param name="watcher"></param> /// <param name="autoAck">If set to true, the msg will be acked after processed</param> /// <param name="batchSize"></param> /// <param name="startThread">Whether should start the consuming thread straight away</param> protected BurrowConsumer(IModel channel, IMessageHandler messageHandler, IRabbitWatcher watcher, bool autoAck, int batchSize, bool startThread) : base(channel, new SharedQueue <BasicDeliverEventArgs>()) { if (channel == null) { throw new ArgumentNullException(nameof(channel)); } if (messageHandler == null) { throw new ArgumentNullException(nameof(messageHandler)); } if (watcher == null) { throw new ArgumentNullException(nameof(watcher)); } if (batchSize < 1) { throw new ArgumentException("batchSize must be greater than or equal 1", nameof(batchSize)); } Model.ModelShutdown += WhenChannelShutdown;; Model.BasicRecoverAsync(true); BatchSize = batchSize; _pool = new SafeSemaphore(watcher, BatchSize, BatchSize); _watcher = watcher; _autoAck = autoAck; _messageHandler = messageHandler; _messageHandler.HandlingComplete += MessageHandlerHandlingComplete; _messageHandler.MessageWasNotHandled += MessageWasNotHandled; if (startThread) { StartConsumerThread($"Consumer thread: {ConsumerTag}"); } }
public void TwoAcquiresOnOnePermitsSemaphoreTest() { int acquire1 = -1, acquire2 = -1; Thread t = new Thread(() => { SafeSemaphore sem = new SafeSemaphore(1, 1); acquire1 = sem.TryAcquire(1) ? 1 : 0; acquire2 = sem.TryAcquire(1) ? 1 : 0; }); t.Start(); bool done = t.Join(2000); if (!done) { TerminateThread(t); Assert.Fail(); } Assert.AreEqual(1, acquire1); Assert.AreEqual(0, acquire2); }
public BurrowConsumer(IModel channel, IMessageHandler messageHandler, IRabbitWatcher watcher, bool autoAck, int batchSize) : base(channel, new SharedQueue()) { if (channel == null) { throw new ArgumentNullException("channel"); } if (messageHandler == null) { throw new ArgumentNullException("messageHandler"); } if (watcher == null) { throw new ArgumentNullException("watcher"); } if (batchSize < 1) { throw new ArgumentNullException("batchSize", "batchSize must be greater than or equal 1"); } Model.ModelShutdown += WhenChannelShutdown; Model.BasicRecoverAsync(true); BatchSize = batchSize; _pool = new SafeSemaphore(watcher, BatchSize, BatchSize); _watcher = watcher; _autoAck = autoAck; _messageHandler = messageHandler; _messageHandler.HandlingComplete += MessageHandlerHandlingComplete; _messageHandler.MessageWasNotHandled += MessageWasNotHandled; Task.Factory.StartNew(() => { try { Thread.CurrentThread.Name = string.Format("Consumer thread: {0}", ConsumerTag); while (!_disposed && !_channelShutdown) { WaitAndHandleMessageDelivery(); } } catch (ThreadStateException tse) { _watcher.WarnFormat("The consumer thread {0} got a ThreadStateException: {1}, {2}", ConsumerTag, tse.Message, tse.StackTrace); } catch (ThreadInterruptedException) { _watcher.WarnFormat("The consumer thread {0} is interrupted", ConsumerTag); } catch (ThreadAbortException) { _watcher.WarnFormat("The consumer thread {0} is aborted", ConsumerTag); } }, TaskCreationOptions.LongRunning); }
public void Ready() { if (_subscription == null) { throw new Exception("Subscription not initialized, call Init first"); } if (PriorityQueue == null) { throw new Exception("PriorityQueue not initialized, call Init first"); } lock (SyncRoot) { _pool = new SafeSemaphore(_watcher, _batchSize, _batchSize, _sharedSemaphore); } Task.Factory.StartNew(() => { try { Thread.CurrentThread.Name = string.Format("Consumer thread: {0}, Priority queue: {1}", ConsumerTag, _queuePriorirty); while (!_disposed && !_channelShutdown) { try { #if DEBUG _watcher.DebugFormat("1. Wait the semaphore to release"); _pool.WaitOne(); _watcher.DebugFormat("2. Semaphore released, wait a msg from RabbitMQ. Probably a wait-for-ack message is blocking this"); #else _pool.WaitOne(); #endif var msg = PriorityQueue.Dequeue(); if (msg != null && msg.Message != null) { #if DEBUG _watcher.DebugFormat("3. Msg from RabbitMQ arrived (probably the previous msg has been acknownledged), prepare to handle it"); #endif HandleMessageDelivery(msg.Message); } else { _watcher.ErrorFormat("Msg from RabbitMQ arrived but it's NULL for some reason, properly a serious BUG :D, contact author asap, release the semaphore for other messages"); _pool.Release(); } } catch (EndOfStreamException) // NOTE: Must keep the consumer thread alive { // This happen when the internal Queue is closed. The root reason could be connection problem Thread.Sleep(100); #if DEBUG _watcher.DebugFormat("EndOfStreamException occurs, release the semaphore for another message"); #endif _pool.Release(); } catch (BadMessageHandlerException ex) { _watcher.Error(ex); Dispose(); } } } catch (ThreadStateException tse) { _watcher.WarnFormat("The consumer thread {0} on queue {1} got a ThreadStateException: {2}, {3}", ConsumerTag, _queuePriorirty, tse.Message, tse.StackTrace); } catch (ThreadInterruptedException) { _watcher.WarnFormat("The consumer thread {0} on queue {1} is interrupted", ConsumerTag, _queuePriorirty); } catch (ThreadAbortException) { _watcher.WarnFormat("The consumer thread {0} on queue {1} is aborted", ConsumerTag, _queuePriorirty); } }, TaskCreationOptions.LongRunning); }