问题
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?
回答1:
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.
回答2:
I don't think async () =>
has the problems you think it does.
Try this:
Action x = async () =>
{
try
{
Console.WriteLine("Hello");
await Task.Delay(TimeSpan.FromSeconds(2.0));
throw new Exception("Wait");
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
Console.WriteLine("Goodbye");
};
var d = Disposable.Create(x);
d.Dispose();
It produces:
Hello Wait Goodbye
来源:https://stackoverflow.com/questions/45286998/async-disposable-create