title: How can I support cancellation of a long running masstransit consumer task when the containing topshelf windows service is stopped
body: <p>I'm using a topshelf windows service to host a masstransit message consumer. One of the consumer tasks can take up to 30 minutes, but is easily interrupted and restarted. When I manually stop the service I would like the consumer task to stop gracefully as soon as possible and to cause masstransit to return the message to the queue where it came from.</p>
  
  <p>I now have this working with a <code>CancellationToken</code> that causes the long running task to throw a <code>TaskCanceledException</code>. In the bus configuration I use the retry configuration to wait until the process is finally killed, thus returning the message to the queue. Is there a better way to implement this? I now get an exception logged by mass transit, and my service doesn't stop as quickly as it should because it is waiting for the <code>Thread.Sleep</code>.</p>
  
  <p><strong>In the long running consumer</strong></p>
  
  <pre><code>if (this.cancellationToken.IsCancellationRequested)
  {
    throw new TaskCanceledException("manual cancel");
  }
  </code></pre>
  
  <p><strong>The retry code in the bus configuration</strong></p>
  
  <pre><code>var busControl = Bus.Factory.CreateUsingRabbitMq(sbc =&gt;
  {
    sbc.UseRetry(x =&gt;
    {
      x.Intervals(this.busConfiguration.RetryIntervals);
      x.Ignore&lt;Exception&gt;(ex =&gt;
      {
        if (cancellationTokenSource.IsCancellationRequested)
        {
            this.loggingService.LogWarning("Worker stopped manually, messages in progress have been returned to the queue.");
  
            // Wait for process to end, this is not great because this causes mass transit to log an error
            Thread.Sleep(TimeSpan.FromDays(1));
        }
        return false;
      });
    });
  }
  </code></pre>
  
  <p><strong>When the service is stopped</strong></p>
  
  <pre><code>public virtual void Stop()
  {
    this.cancellationTokenSource.Cancel();
    this.busHandle.Stop();
  }
  </code></pre>