如果在 using 语句中进行异步调用,并且调用的结果是异步处理的(即,发生这种情况的方法是异步的,并且在加载和处理结果之前返回),那么 using 语句是否会超出范围?
换句话说,做这样的事情是否安全:
async void LoadAndProcessStuff()
{
using(var ctx = CreateDBContext()){
someResource.LoadStuffsAsync().ForEachAsync(stuff => ctx.Stuffs.Add(stuff));
}
}
or
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");
}
}
}
}
但是,如果您有一个返回任务而不是等待任务的非异步方法,则它可能不安全。那是因为同步方法只被调用once。编译器没有生成协程或状态机,因此必须立即调用 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 http://www.thebillwagner.com/Blog/Item/2017-05-03-ThecuriouscaseofasyncawaitandIDisposable
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)