C#中的闭包分配 [英] Closure allocations in C#

查看:77
本文介绍了C#中的闭包分配的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经安装了Clr堆分配分析器扩展,并且在一个项目中看到了我不太了解的东西,我有一个带有签名的方法

 公共任务< int> ExecuteAsync(字符串sql,动态参数= null,IDbTransaction transaction = null,int?commandTimeout = null,CommandType?commandType = null)
{
param = SetModificationValuesForGlobalRing(param);
return _sqlPolicy.ExecuteAsync(async()=>
{
int结果;
使用(var connection = new SqlConnection(_connectionString))
{
await connection.OpenAsync();
result = await connection.ExecuteAsync(sql,param as object,transaction,commandTimeout,commandType);
}
返回结果;
}) ;
}

此工具向我警告方法和所有表示以下内容的参数


编译器将发出一个将其保存为字段的类,以允许捕获此闭包。


我不知道为什么会这样,是由于可选参数引起的吗?

解决方案

您必须是:


  1. 从lambda之类的匿名函数中调用此代码。




    • 或-


  2. 在某处使用yield / await关键字。


使用上述两种方法时,C#必须创建一个闭包来捕获在闭包内使用的,超出原始范围(在第一种情况下)或在yield / await之后的之前使用的变量(在第二种情况下)。
$ b

C#通过创建一个匿名类-在编译时定义-在内存中。然后,它在该匿名类上为其需要保留的每条信息创建一个字段。这可能会导致对象实例的生存期延长到闭包生命周期或具有yield / await的方法的生命周期。



有时生命周期比原来更长。您未使用yield / await或lambda。在这种情况下,您可能会注意到内存使用量超出了预期(因为垃圾收集器将不会收集对象实例,直到关闭完全超出范围或包含yield / await的方法已完成)。



您看到的警告只是您的工具试图向您解释以上内容,因此您知道会发生这种情况并可能导致内存增加用法。


I've installed the Clr Heap Allocation Analyzer extension and in a project I see something that I quite don't understand, I've got a method with a signature

public Task<int> ExecuteAsync(string sql, dynamic param = null, IDbTransaction transaction = null, int? commandTimeout = null, CommandType? commandType = null)
{
    param = SetModificationValuesForGlobalRing(param);
    return _sqlPolicy.ExecuteAsync(async () =>
    {
        int result;
        using (var connection = new SqlConnection(_connectionString))
        {
            await connection.OpenAsync();
            result = await connection.ExecuteAsync(sql, param as object, transaction, commandTimeout, commandType);
        }
        return result;
    });
}

This tools' giving me a warning on the method and all the parameters that says

The compiler will emit a class that will hold this as a field to allow capturing of this closure.

I don't know why this behaviour happens, is it due to the optional parameters?

解决方案

You must be:

  1. Calling this code from within an anonymous function, like a lambda.

    • or -
  2. Using the yield/await keyword somewhere.

When you use either of the above, C# must create a closure to capture any variables used within the closure that have an originating scope outside of your lambda (in the first case) or usage before and after the yield/await (in the second case).

C# captures the closure by creating an anonymous class -- defined at compile-time -- in memory. It then creates a field on that anonymous class for each piece of information it needs to persist. This can result in an object instance's lifetime being extended for the life of the closure or the life of the method with the yield/await.

Sometimes the lifetime is longer than had you NOT used yield/await or the lambda. In that case, you might notice memory usage that is higher than you expected (as the garbage collector won't collect the object instance until the closure is completely out of scope or the method containing the yield/await has completed).

The warning you see is simply your tool trying to explain the above to you, so that you know to expect this behavior and the resulting potential increase in memory usage.

这篇关于C#中的闭包分配的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆