异步 Disposable.Create
Async Disposable.Create
Disposable.Create 需要一个 Action
作为参数。当处理 Rx 订阅时,Action
是 运行。
在处理 Rx 订阅时,我想 运行 一些异步清理代码,但是使用 async () =>
和 Action
与 async void
相同,我想避开。有关我为什么要避免这种情况的更多详细信息,请参阅 here。
是否可以创建类似 Disposable.AsyncCreate
的东西,它接受 Func<Task>
而不是 Action
。如果是这样,我应该如何将其用作 CompositeDisposable
的一部分?
或者是否有其他模式来处理异步处置?
我认为 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();
它产生:
Hello
Wait
Goodbye
你可以这样做。我仍然不确定这个想法有多好:
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()
语句,class DisposableAsync
应该得到加强。除此之外,我想不出它有什么问题,但我倾向于(咳咳)反对它。只是感觉有点hacky。
Disposable.Create 需要一个 Action
作为参数。当处理 Rx 订阅时,Action
是 运行。
在处理 Rx 订阅时,我想 运行 一些异步清理代码,但是使用 async () =>
和 Action
与 async void
相同,我想避开。有关我为什么要避免这种情况的更多详细信息,请参阅 here。
是否可以创建类似 Disposable.AsyncCreate
的东西,它接受 Func<Task>
而不是 Action
。如果是这样,我应该如何将其用作 CompositeDisposable
的一部分?
或者是否有其他模式来处理异步处置?
我认为 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();
它产生:
Hello Wait Goodbye
你可以这样做。我仍然不确定这个想法有多好:
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()
语句,class DisposableAsync
应该得到加强。除此之外,我想不出它有什么问题,但我倾向于(咳咳)反对它。只是感觉有点hacky。