【问题标题】:From an async method, is calling a LINQ query's ToList, instead of ToListAsync, a potential deadlock?从异步方法调用 LINQ 查询的 ToList,而不是 ToListAsync,是否会导致死锁?
【发布时间】:2020-01-17 10:48:23
【问题描述】:

我遇到了一种情况,我需要单个 LINQ 查询以非异步方式运行。原因:目前在异步 EF 调用如何加载大 blob 方面仍然存在一个错误(更多信息 Entity Framework async operation takes ten times as long to complete

所以我修复上述错误的选项是将查询转换为自定义 DbCommand 并异步运行原始 SQL,或者我可以将调用从 ToListAsync 更改为 ToList .

TLDR --- 问题: 我知道同步调用异步代码会导致死锁(例如query.ToListAsync().Result),但是,在异步方法中调用非异步版本的 ToList 是否有同样的问题?

【问题讨论】:

  • List 将保存其中的每个对象,大型 List 将消耗大量内存。我建议您 IQueryable 通常是流式传输的,它们像 IEnumerable 一样被使用,并且不需要将返回的所有元素保存在内存中。要在异步方法中使用 ToList,您必须使用 Task.Run(() =>) 和 Task.Wait();否则会注意完成任务

标签: c# async-await deadlock


【解决方案1】:

我知道同步调用异步代码会导致死锁(例如query.ToListAsync().Result),但是在异步方法中调用非异步版本的ToList 是否有同样的问题?

调用像ToList() 这样的同步方法会阻塞当前线程,无论您是否在本应为异步的方法中执行此操作。所以它不会死锁,但会阻塞调用方法。而且您不希望异步阻塞。请记住,async 方法与任何其他方法一样同步运行,直到遇到 await

【讨论】:

    【解决方案2】:

    如果您使用,您可以保留异步等待签名而不会出现编译器警告

    return await Task.FromResult(query.ToList());
    

    【讨论】:

    • await Task.FromResult(query.ToList())query.ToList() 相同,但没有开销。
    猜你喜欢
    • 2020-01-12
    • 1970-01-01
    • 2017-02-18
    • 1970-01-01
    • 2021-07-13
    • 1970-01-01
    • 1970-01-01
    • 2018-05-07
    • 1970-01-01
    相关资源
    最近更新 更多