在IDisposable.Dispose()中使用异步调用

7

我需要实现一个简单的事务。为此,我的事务类实现了IDisposable接口。这样,我可以在using语句中使用我的事务类,如果在该范围内发生任何错误,则当事务被处理时,所有内容都会回滚。

using (var transaction = new Transaction())
{
    // do some stuff
}

"do some stuff"也包括一些客户端/服务器连接等操作。
如果"do some stuff"出现任何错误,现在我会回滚所有操作。
public async void Dispose(){ // roll back everything on error }

这可能包括在需要调用异步操作的服务器上清理一些资源。这引出了我的问题:我可以安全地只使用async关键字来实现Dispose()以在其实现中启用await关键字吗?或者这可能会由于同步上下文问题等原因导致竞争条件?


1
一些有趣的阅读 http://blog.stephencleary.com/2013/03/async-oop-6-disposal.html - Gusdor
3个回答

5
如何调用 Task.Run(...) 呢?它会将指定的工作排队到线程池上运行。
    public void Dispose()
    {
        if (_thereWasAnError)
        {
            Task.Run(async () => await RollbackAsync()).Wait();
        }
    }

4
如果你做类似这样的事情,一定要小心死锁的情况。例如,如果你从UI线程调用dispose,并且你的RollbackAsync有其他在UI线程上等待的操作,那么就会发生死锁。可能更安全的方法是只调用"var result = RollbacAsync().Result;"。 - rollsch

2
您只能在方法返回TaskTask<T>或其他可等待实现时使用awaitIDisposable未定义Task Dispose()方法。您总是可以编写自己的方法,但当您退出using块时它将不会被调用。
根据资源中的锁定机制,使用async void可能会存在竞态条件(应避免使用!)。

2

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接