功能仍然异步可以改进吗?

时间:2014-06-15 10:52:23

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

我有这个功能:

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;
}

2 个答案:

答案 0 :(得分:3)

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

  

原因是ASP.NET运行时不知道你已将这项工作排队(使用Task.Run),因此它不知道后台工作是否存在。出于各种原因,IIS / ASP.NET必须偶尔回收您的应用程序。如果你在回收过程中运行了后台工作,那么这项工作将会神秘地消失。

当我围绕某些异步操作(数据库查询,Web请求等)创建async方法时,我坚持使用&#34;异步方法应该命中await的规则尽快声明&#34;,这是因为await之前的任何代码都将同步运行。您可以选择使用ConfigureAwait(false)来避免返回到您的请求上下文,但这通常会很快发生。有关详情,请参阅Best practice to call ConfigureAwait for all server-side code

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

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

答案 1 :(得分:1)

通常,您需要等待I / O等相对较长时间运行的任务。所以,等待你对存储库提取的调用是一件好事。你的ForEach循环根本不是很糟糕,但是如果你的存储库提取只返回你实际需要的数据,它可能会表现得更好,因为它不会返回所有数据。

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

然后我们应该考虑这是网络电话和等待实际上只是释放请求处理程序,以便它可能不会使每个人的呼叫更快,它只是不会占用坐在那里等待的请求用于数据库I / O.

你总是可以放入一些Stopwatches来查看事情需要多长时间。