Disposable.Create 需要一个Action
作为参数。Action
在释放 Rx 订阅时运行。
在处理 Rx 订阅时,我想运行一些异步清理代码,但是将async () =>
与Action
一起使用与async void
相同,我想避免这种情况。有关我为什么要避免这种情况的更多详细信息,请参阅此处。
是否有可能创建类似Disposable.AsyncCreate
的东西,它接受Func<Task>
而不是Action
.如果是这样,我应该如何将其用作CompositeDisposable
的一部分?
还是有其他模式来处理异步处置?
你可以做这样的事情。我仍然不确定这是一个多好的想法:
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);
}
}
然后你可以像这样使用它:
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");
}
此解决方案不适用于using()
语句,类DisposableAsync
应该可靠。除此之外,我想不出它有什么问题,但我倾向于(咳咳(反对它。只是感觉有点笨拙。
我不认为async () =>
有你认为的问题。
试试这个:
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();
它产生:
你好 等 再见