Disposable.Create require an Action
as parameter. The Action
is run when the Rx subscription is being disposed.
When disposing a Rx subscription I’d like to run some asynchronous clean up code, however using async () =>
with Action
is identical to async void
, which I’d like to avoid. For more details on why I want to avoid this, see here.
Is it possible to create something like a Disposable.AsyncCreate
, which accepts Func<Task>
rather than Action
. If so how should I use it as part of a CompositeDisposable
?
Or are there other patterns for dealing with asynchronous Disposal?
You could do something like this. I'm still not sure how good an idea it is:
public class DisposableAsync
{
private readonly IDisposable _disposable;
private readonly Func<Task> _asyncDisposalAction;
public DisposableAsync(IDisposable disposable, Func<Task> asyncDisposalAction)
{
_disposable = disposable;
_asyncDisposalAction = asyncDisposalAction;
}
public Task DisposeAsync()
{
_disposable.Dispose();
return _asyncDisposalAction();
}
}
public static class DisposableAsyncExtensions
{
public static DisposableAsync ToAsync(this IDisposable disposable, Func<Task> asyncDisposalAction)
{
return new DisposableAsync(disposable, asyncDisposalAction);
}
}
You could then use it like this:
async Task Go()
{
var o = Observable.Interval(TimeSpan.FromMilliseconds(100));
var d = o
.Subscribe(i => Console.WriteLine($"{DateTime.Now.ToLongTimeString()}: {i}"))
.ToAsync(async () =>
{
Console.WriteLine($"{DateTime.Now.ToLongTimeString()}: Dispose Beginning");
await Task.Delay(1000);
Console.WriteLine($"{DateTime.Now.ToLongTimeString()}: Dispose Complete");
});
Console.Read();
var t = d.DisposeAsync();
Console.WriteLine($"{DateTime.Now.ToLongTimeString()}: Outside task, waiting for dispose to complete");
await t;
Console.WriteLine($"{DateTime.Now.ToLongTimeString()}: Task Complete");
}
This solution wouldn't work with using()
statements, and the class DisposableAsync
should be robustified. Outside of that, I can't think of anything wrong with it, but I'm predisposed (ahem) against it though. Just feels kind of hacky.