【问题标题】:Function still async can it be refined?函数还是 async 可以细化吗?
【发布时间】:2015-02-12 18:22:40
【问题描述】:

我有这个功能:

public async Task<string> EagerLoadAllAsync<T>(params Expression<Func<T, object>>[] includeProperties) where T : class
{
    var entities = await _repository.EagerLoadAllAsync(includeProperties);
    entities.ForEach(l =>
    {
        var lead = l as Lead;
        if (lead.User != null) 
        {
            // We must reduce the amount of data being sent to the client side
            lead.User = new Domain.Identities.ApplicationUser { FirstName = lead.User.FirstName, LastName = lead.User.LastName, UserName = lead.User.UserName };
        }
    });

    var json = await Task.Factory.StartNew(() => JsonConvert.SerializeObject(entities, Formatting.Indented, new JsonSerializerSettings { 
        ReferenceLoopHandling = ReferenceLoopHandling.Ignore
    }));

    return json;
}

我认为它仍然是 async 它必须运行 awaitable 函数,一个从数据库中获取数据,另一个将其转换为 json

我想知道中间的ForEach 循环是否会从根本上破坏async

有没有办法让这个更async? 是不是应该更多async

在我需要减少发送到客户端的数据之前,我有这个功能:

public async Task<string> EagerLoadAllAsync<T>(params Expression<Func<T, object>>[] includeProperties) where T : class
{   
    var json = await Task.Factory.StartNew(async() => JsonConvert.SerializeObject(await await _repository.EagerLoadAllAsync(includeProperties), Formatting.Indented, new JsonSerializerSettings { 
        ReferenceLoopHandling = ReferenceLoopHandling.Ignore
    }));

    return json.Result;
}

【问题讨论】:

    标签: c# .net asp.net-mvc asynchronous async-await


    【解决方案1】:

    Stephan cleary 有一篇关于 the dangers of using Task.Run in ASP.NET 的精彩博文:

    原因是 ASP.NET 运行时不知道您已将该工作排队(使用 Task.Run),因此它甚至不知道后台工作是否存在。由于各种原因,IIS/ASP.NET 不得不偶尔回收您的应用程序。如果在进行此回收时您正在运行后台工作,那么该工作将神秘地消失。

    当我围绕一些异步操作(数据库查询、Web 请求等)创建 async 方法时,我坚持“异步方法应尽快命中其 await 语句”的规则,那是因为等待之前的任何代码都会同步运行。您可以选择使用ConfigureAwait(false) 来避免返回到您的请求上下文,但这通常会很快发生。有关更多信息,请参阅Best practice to call ConfigureAwait for all server-side code

    关于ForEach,我肯定会对该部分进行基准测试,看看它对异步调用的影响有多大。除此之外,请阅读关于 ForEach vs foreach 的 eric lipperts 帖子,了解为什么不应该使用它。

    为了 JSON 反序列化,我肯定会继续旋转一个新的 ThreadPool 线程。调用该线程然后同步运行它会花费更多。如果您的 JSON 不是很大,请使用同步方法。

    【讨论】:

    • 前几天我真的读到了,不知道为什么没看懂,可能太累了:P
    • 我的博文实际上是在谈论使用Task.Run/Task.Factory.StartNew/etc 没有 await。如果您使用await,则Task.Run 代码在逻辑上被视为该请求的一部分,并且不会“消失”。但是,出于效率原因,我仍然不推荐在 ASP.NET 上使用 Task.Run
    • 我指的是使用Task.Run 而不使用await 的更一般情况。在这种特殊情况下,甚至不需要它。
    【解决方案2】:

    通常,您等待运行时间相对较长的任务,例如 I/O。因此,等待您调用存储库获取是一件好事。您的 ForEach 循环一点也不差,但如果您的存储库 fetch 只返回您实际需要的数据,它可能会执行得更好,因为它不会返回所有这些数据。

    不过,我不确定启动另一项将实体转换为 json 的任务是否对您有任何好处。

    然后我们应该考虑这是网络调用,await 实际上只是释放请求处理程序,因此它可能不会使每个单独的调用更快,它只是不会绑定一个正在等待数据库的请求输入输出。

    您可以随时输入一些Stopwatches 以查看需要多长时间。

    【讨论】:

    • 是的,我就是这么想的,在请求-响应模型中它并没有太大的区别。我正在关注 JSON.NET 在他的示例中显示的转换,如果存储库有很多信息,那么执行后台任务可能就可以了。
    猜你喜欢
    • 2016-07-21
    • 2012-05-24
    • 2015-11-19
    • 2013-07-21
    • 1970-01-01
    • 1970-01-01
    • 2016-01-02
    • 1970-01-01
    • 2021-04-10
    相关资源
    最近更新 更多