Rx.Net的Using操作符是否支持搭配实现IAsyncDisposable的资源使用
Rx.NET Using操作符对IAsyncDisposable资源的支持说明
原生Observable.Using操作符默认仅支持实现了IDisposable接口的同步释放资源,不直接适配IAsyncDisposable类型的异步释放资源,低版本Rx.NET中直接传入IAsyncDisposable实例会触发编译错误。
可行的替代解决方案
- 方案1:升级到Rx.NET 5.0及以上版本
高版本Rx.NET已经官方新增了支持IAsyncDisposable的Using重载,你可以直接传入返回IAsyncDisposable的资源工厂方法,框架会自动在序列终止时完成异步释放逻辑,无需额外封装,使用方式和原有Using保持一致:var sequence = Observable.Using( () => new YourAsyncDisposableResource(), // 该资源实现IAsyncDisposable resource => resource.GetObservableData() ); - 方案2:自定义异步Using扩展方法(兼容低版本Rx.NET)
如果受项目约束无法升级Rx.NET版本,可以自行封装UsingAsync扩展方法处理异步资源的创建和释放逻辑,参考实现如下:public static IObservable<T> UsingAsync<TResource, T>( Func<Task<TResource>> resourceFactory, Func<TResource, IObservable<T>> observableFactory) where TResource : IAsyncDisposable { return Observable.Create<T>(async (observer, ct) => { var resource = await resourceFactory().ConfigureAwait(false); try { var source = observableFactory(resource); var subscription = source.Subscribe(observer); return Disposable.Create(async () => { subscription.Dispose(); await resource.DisposeAsync().ConfigureAwait(false); }); } catch { await resource.DisposeAsync().ConfigureAwait(false); throw; } }); } - 方案3:适配
IAsyncDisposable为IDisposable(临时过渡方案)
如果仅需要快速兼容原有代码,可以做简单的适配包装,但该方案会同步阻塞等待异步释放完成,存在死锁风险,不推荐在高并发或UI线程场景使用:
适配类实现:
使用示例:public sealed class AsyncDisposableWrapper : IDisposable { private readonly IAsyncDisposable _target; public AsyncDisposableWrapper(IAsyncDisposable target) { _target = target ?? throw new ArgumentNullException(nameof(target)); } public void Dispose() => _target.DisposeAsync().AsTask().Wait(); }var sequence = Observable.Using( () => new AsyncDisposableWrapper(new YourAsyncDisposableResource()), wrapper => ((YourAsyncDisposableResource)wrapper.Target).GetObservableData() );
内容的提问来源于stack exchange,提问作者jack
相关产品推荐
相关产品推荐

