c# - 没有await的using语句中的async,这安全吗?

标签 c# asynchronous using

如果在 using 语句中进行异步调用,并且调用的结果是异步处理的(即发生这种情况的方法是异步的,并且在结果加载和处理之前返回),则 using 语句是否可以退出范围? 换句话说,做这样的事情是否安全:

async void LoadAndProcessStuff()
{
    using(var ctx = CreateDBContext()){
        someResource.LoadStuffsAsync().ForEachAsync(stuff => ctx.Stuffs.Add(stuff));
    }
}

async void LoadAndProcessStuff2()
{
    using(var ctx = CreateDBContext()){
        ctx.Stuffs.Select(stuff => someResource.LoadMoreStuffsAsync(stuff))
            .ForEachAsync(stuff => ctx.Stuffs2.AddRange(stuff.Result));
    }
}

或者 ctx 是否可以在调用 ForEachAsync 时被 Dispose 并导致异常?

最佳答案

在异步方法中,“using”关键字应该是安全的。编译器只是将其重写为“finally”表达式,其工作方式与异步方法中的所有其他异常处理类似。请注意,Dispose() 不应阻塞或长时间运行,它应该只释放资源 - 除非您想瘫痪您的服务器。

这是安全案例的简单测试案例:

using System;
using System.Threading.Tasks;

namespace so {
    sealed class Garbage : IDisposable {
        public void Dispose() {
            Console.WriteLine("Disposing Garbage");
        }
    }

    // Garbage is safely Disposed() only after delay is done
    class Program {
        public static async Task Main() {
            using (Garbage g = new Garbage()) {
                Console.WriteLine("Delay Starting");
                await Task.Delay(1000);
                Console.WriteLine("Delay Finished");
            }
        }
    }
}

但是,如果您有一个返回任务而不是等待任务的非异步方法,则可能不安全。这是因为同步方法仅被调用一次。编译器没有生成协程或状态机,因此必须立即调用 Dispose() - 可能在任务仍在运行时调用。

public Task DoWorkAsync()
{
    using (var service = new Service())
    {
        var arg1 = ComputeArg();
        var arg2 = ComputeArg();

        // NOT SAFE - service will be disposed
        // There is a high-probability that this idiom results 
        // in an ObjectDisposedException
        return service.AwaitableMethodAsync(arg1, arg2);
    }
}

引用:http://www.thebillwagner.com/Blog/Item/2017-05-03-ThecuriouscaseofasyncawaitandIDisposable

关于c# - 没有await的using语句中的async,这安全吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48126982/

相关文章:

c# - SQL更新丢失顺序的列?

c# - 检查列表中的间隔是否等长

c# - 无法让 Costura.Fody 工作,一直要求 DLL

javascript - 移动设备上的 AJAX 请求不起作用

C++ 不使用 使用

c++ - "using namespace std"有什么用?

c# - 有没有一种方法可以更改命令前缀而无需重新启动机器人以使更改生效? (DSharpPlus)

c# - 有什么方法可以使用 Wpf (C#) 更改 Web 浏览器的上下文菜单

javascript - 异步迭代时的node.js数据一致性

python - Celery 4.0.2 AsyncResult.then 不工作