Pass async function to parameter with type of Action<X>?

79 views Asked by At

The application has the following definition

IDisposable IObservable<X>.Subscribe<X>(Action<X> onNext)

It was passed an async function:

async Task Process(X notification, CancellationToken ct) {...}

source.Subscribe(async x => await Process(x, CancellationToken.None)); // Warning

However, ReSharper warns "avoid using 'async' lambda when delegate type returns 'void'", because the exception raised in Process will not be caught with Catch.

The following code doesn't have any warning. However, I heard using Wait() is usually a bad code smell?

source.Subscribe(x => Process(x, CancellationToken.None).Wait());
1

There are 1 answers

1
L01NL On

When you call an async function in the Subscribe Action then you create an async void method. It is good to always avoid async void as Resharper correctly states , since potential exceptions are disappearing in the void.

A better way to call an async function is like this: Also note the catching of the exceptions.

source
   .Select(result =>
       Observable.FromAsync(() => observer.OnCalculationFinished(result))
          .Catch((Exception ex) =>
          {
             Log.Error(ex, "Error on VEV calculation subscription for client {Client} {Quarter}.", result.VevQuarterCalculation.ClientId, result.VevQuarterCalculation.Quarter);
             return Observable.Empty<System.Reactive.Unit>();
           }))
   .Concat()
   .Subscribe();