Hi,
My basic workflow is this:
- message consumer reads message from queue
- event handler attempts to write to disk
- but disk is full, or perhaps no permission to write to disk
- I want to throw an exception from the event handler
and have it bubble all the way up to the caller
- the caller, in my case, is a Windows Service
and I want my Windows Service to decide what to do (- e.g. shut itself down)
The problem?
* I try to throw an exception in my EventHandler, but it doesn't get caught.
What's the appropriate behavior? Should EventHandlers be throwing exceptions? If not, how should I be handling and communicating these errors to the host/caller?
Thanks!
Here's a code snippet:
public void StartConsumer(string queueName, CancellationToken token)
{
IConnection conn = this.GetConnection();
try
{
using (IModel channel = conn.CreateModel())
{
channel.BasicRecoverOk += (x, eventArgs) =>
this.HandleChannelBasicRecoverOk(channel, eventArgs, queueName, token);
// create our consumer
var consumer = new EventingBasicConsumer(channel);
consumer.Received += (x, eventArgs) =>
this.HandleConsumerReceived(channel, eventArgs, queueName, token, (EventingBasicConsumer)x);
consumer.ConsumerCancelled += (x, eventArgs) =>
this.HandleConsumerCancelled(channel, eventArgs, queueName, token, (EventingBasicConsumer)x);
consumer.Shutdown += (x, eventArgs) =>
this.HandleConsumerShutdown(channel, eventArgs, queueName, token, (EventingBasicConsumer) x);
channel.BasicConsume(queue: queueName, noAck: false, consumer: consumer);
// spin-wait
while (!token.IsCancellationRequested)
{
Thread.Sleep(250);
}
if (token.IsCancellationRequested)
{
if (channel.IsOpen)
channel.BasicCancel(consumer.ConsumerTag);
}
}
}
catch (Exception ex)
{
_logService.WriteError(ex);
throw;
}
}
private void HandleConsumerReceived(IModel channel, BasicDeliverEventArgs eventArgs,
string queueName, CancellationToken token, EventingBasicConsumer consumer)
{
try
{
string message = System.Text.Encoding.UTF8.GetString(eventArgs.Body);
_myMessageProcessor.Run(message)
}
catch (Exception ex)
{
channel.BasicNack(deliveryTag: eventArgs.DeliveryTag, multiple: false, requeue: true);
throw new MyCustomException("Message Processor threw an unexpected exception", ex);
}
}