Async Disposable.Create

老子叫甜甜 提交于 2019-12-07 05:54:00

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!