diff --git a/projects/RabbitMQ.Client/client/impl/ModelBase.cs b/projects/RabbitMQ.Client/client/impl/ModelBase.cs index 3510ac070e..db0e072451 100644 --- a/projects/RabbitMQ.Client/client/impl/ModelBase.cs +++ b/projects/RabbitMQ.Client/client/impl/ModelBase.cs @@ -681,7 +681,10 @@ public void HandleBasicCancelOk(string consumerTag) k.m_consumer = DefaultConsumer; } - ConsumerDispatcher.HandleBasicCancelOk(k.m_consumer, consumerTag); + if (!(k.m_consumer is null)) + { + ConsumerDispatcher.HandleBasicCancelOk(k.m_consumer, consumerTag); + } k.HandleCommand(IncomingCommand.Empty); // release the continuation. } @@ -1073,7 +1076,10 @@ public void BasicCancel(string consumerTag) _consumers.Remove(consumerTag); } - ModelShutdown -= k.m_consumer.HandleModelShutdown; + if (!(k.m_consumer is null)) + { + ModelShutdown -= k.m_consumer.HandleModelShutdown; + } } public void BasicCancelNoWait(string consumerTag) diff --git a/projects/Unit/TestBasicCancelAnyConsumer.cs b/projects/Unit/TestBasicCancelAnyConsumer.cs new file mode 100644 index 0000000000..04638ae697 --- /dev/null +++ b/projects/Unit/TestBasicCancelAnyConsumer.cs @@ -0,0 +1,37 @@ +using System; +using System.Threading; +using NUnit.Framework; +using RabbitMQ.Client.Events; + +namespace RabbitMQ.Client.Unit +{ + [TestFixture] + public class TestBasicCancelAnyConsumer : IntegrationFixture + { + [Test] + public void TestBasicCancelWithQueueDelete() + { + // Arrange + Exception modelException = null; + Model.CallbackException += HandleCallbackException; + Model.QueueDeclare(TestContext.CurrentContext.Test.Name, false, false, false); + string consumerTag = Model.BasicConsume(TestContext.CurrentContext.Test.Name, false, new VoidConsumer()); + + // Act + WithTemporaryModel(m => m.QueueDelete(TestContext.CurrentContext.Test.Name)); + TestDelegate act = () => Model.BasicCancel(consumerTag); + + // Assert + Assert.DoesNotThrow(act); + SpinWait.SpinUntil(() => !(modelException is null), TimingFixture.TestTimeout); + Assert.IsNull(modelException, "The model has thrown an exception when cancelling a consumer after the queue has been deleted. This exception comes from the scheduling of CancelOk Action."); + + // Cleanup + Model.CallbackException -= HandleCallbackException; + + void HandleCallbackException(object sender, CallbackExceptionEventArgs e) => modelException = e.Exception; + } + + private sealed class VoidConsumer : DefaultBasicConsumer{} + } +}