I have the following Reactive Extensions Subject
and need to log exceptions, and also shutdown this potentially blocking async task created on Observable.FromAsync
cleanly.
In relation to this and on cancelling the token, the exception TaskCanceledException
would be thrown by anything waiting on the token.
How can i trap these exceptions - ignoring the TaskCanceledException
as that is expected on shutdown, and logging the rest?
internal sealed class TradeAggregator : IDisposable
{
private readonly Subject<TradeExecuted> feed = new();
private readonly CancellationTokenSource cts = new();
private bool isStopped;
private bool isDisposed;
public TradeAggregator(Func<TradeAggregate, CancellationToken, Task> dispatch)
{
feed
.GroupByUntil(x => (x.Execution.Contract.Symbol, x.Execution.AccountId, x.Tenant, x.UserId), x => Observable.Timer(TimeSpan.FromSeconds(5)))
.SelectMany(x => x.ToList())
.Select(trades => Observable.FromAsync(() => dispatch(AggregateTrades(trades), cts.Token)))
.Concat() // Ensure that the results are serialized.
.Subscribe(cts.Token); // Check status of calls.
}
private TradeAggregate AggregateTrades(IEnumerable<TradeExecuted> trades)
{
// Do stuff.
return new TradeAggregate();
}
public void OnNext(ExecutedTrade trade) => this.feed.OnNext(trade);
public void Stop()
{
if (isStopped) return;
isStopped = true;
cts.Cancel();
}
public void Dispose()
{
if (isDisposed) return;
isDisposed = true;
Stop();
feed.Dispose();
cts.Dispose();
}
}