public async Task Run(CancellationToken cancellationToken = default(CancellationToken)) {
TaskUtilities.AssertIsOnBackgroundThread();
if (_runTask != null) {
throw new InvalidOperationException("This host is already running.");
}
var cts = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, _cts.Token);
try {
_runTask = RunWorker(cts.Token);
await _runTask;
} catch (OperationCanceledException) when (cancellationToken.IsCancellationRequested || _cts.Token.IsCancellationRequested) {
// Expected cancellation, do not propagate, just exit process
} catch (MessageTransportException ex) when (cancellationToken.IsCancellationRequested || _cts.Token.IsCancellationRequested) {
// Network errors during cancellation are expected, but should not be exposed to clients.
throw new OperationCanceledException(new OperationCanceledException().Message, ex);
} catch (Exception ex) {
var message = "Exception in RHost run loop:\n" + ex;
_log.WriteLineAsync(LogVerbosity.Minimal, MessageCategory.Error, message).DoNotWait();
Debug.Fail(message);
throw;
} finally {
cts.Dispose();
// Signal cancellation to any callbacks that haven't returned yet.
_cts.Cancel();
_requests.Clear();
}
}