gpt4 book ai didi

c# - C# 异步库方法调用是否应该等待?

转载 作者:可可西里 更新时间:2023-11-01 09:12:49 25 4
gpt4 key购买 nike

异步库方法是否应该调用await?例如,假设我有一个数据服务库方法可以访问名为“repository”的 Entity Framework 6 数据上下文。据我所知,我有两种定义此方法的方法:

public static async Task<IEnumerable<Blogs>>
GetAllBlogsAsync(EfDataContext db)
{
return await db.Blogs
.OrderByDescending(b => b.Date)
.SelectAsync();
}

或者没有async/await装饰

public static Task<IEnumerable<Blogs>>
GetAllBlogsAsync(EfDataContext db)
{
return db.Blogs
.OrderByDescending(b => b.Date)
.SelectAsync();
}

在应用程序端点,在本例中为 MVC Controller 操作,两种方法的调用都是相同的:

public async Task<ActionResult> Blogs()
{
var blogs = await BlogService.GetAllBlogs(_blogRepository);
return View(blogs);
}

当然,如果应用程序调用一系列异步方法,这种情况可能会更加复杂。链中的每个方法都应该调用 await,还是在调用链的末尾只有一个 await 语句,这会有什么区别?

最佳答案

将一次性对象传递给异步方法时应该小心。

using (var db = new EfDataContext())
{
return BlogService.GetAllBlogs(db);
}

如果您在执行查询的任务完成之前释放 DataContext,您可能会收到 ObjectDisposedException(或访问已释放的上下文所产生的任何其他类型)。

如果您可以确保在处理上下文之前正在等待任务,则最好简单地返回任务(不使用异步),因为它会减少一个步骤。

编辑:

虽然它最常见于 using block 中的一次性对象,但对于在任务完成之前更改对象状态的所有类型的引用也是如此。

例如,一旦您调用 await TestAsync();

,以下示例将抛出 DivideByZeroException
public class MyClass
{
public int Value { get; set; }
}

public static async Task<int> DivideAsync(MyClass myClass)
{
await Task.Yield();
return 2 / myClass.Value;
}

public static Task<int> TestAsync()
{
MyClass myClass = new MyClass { Value = 4 };
Task<int> result = DivideAsync(myClass);
myClass.Value = 0;
return result;
}

所以恕我直言,如果您要更改任务将使用的对象的状态,最好等待任务。

关于c# - C# 异步库方法调用是否应该等待?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36494144/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com