Resharper:隐含捕获闭合:这个

Aar*_*len 65 .net c# resharper

我从Resharper得到这个警告("Implicity capture closure:this"):这是否意味着这个代码以某种方式捕获整个封闭对象?

    internal Timer Timeout = new Timer
                            {
                                Enabled = false,
                                AutoReset = false
                            };
    public Task<Response> ResponseTask
    {
        get
        {
            var tcs = new TaskCompletionSource<Response>();

            Timeout.Elapsed += (e, a) => tcs.SetException(new TimeoutException("Timeout at " + a.SignalTime));

            if (_response != null) tcs.SetResult(_response);
            else ResponseHandler += r => tcs.SetResult(_response);
            return tcs.Task;
        }
    }
Run Code Online (Sandbox Code Playgroud)

我不确定它是如何或为什么这样做 - 它应该捕获的唯一变量是TaskCompletionSource,这是故意的.这实际上是一个问题,如果是这样我将如何解决?

编辑:警告在第一个lambda(Timeout事件)上.

Aar*_*len 27

似乎问题不在于我认为的问题.

问题是我有两个lambdas引用父对象中的字段:编译器生成一个具有两个方法的类和一个对父类的引用(this).

我认为这将是一个问题,因为引用this可能会留在TaskCompletionSource对象中,从而阻止它被GCed.至少我在这个问题上发现的就是这个.

生成的类看起来像这样(显然名称将是不同的和不可发音的):

class GeneratedClass {
    Request _this;
    TaskCompletionSource tcs;

    public lambda1 (Object e, ElapsedEventArgs a) {
        tcs.SetException(new TimeoutException("Timeout at " + a.SignalTime));
    }

    public lambda2 () {
        tcs.SetResult(_this._response);
    }
}
Run Code Online (Sandbox Code Playgroud)

编程执行此操作的原因可能是效率,我想,因为TaskCompletionSourcelambdas使用了它; 但是现在只要仍然引用对其中一个lambdas的引用,Request也会保持对对象的引用.

不过,我仍然没有找到如何避免这个问题.

编辑:当我写这篇文章时,我显然没有想到这一点.我通过改变这样的方法解决了这个问题:

    public Task<Response> TaskResponse
    {
        get
        {
            var tcs = new TaskCompletionSource<Response>();

            Timeout.Elapsed += (e, a) => tcs.SetException(new TimeoutException("Timeout at " + a.SignalTime));

            if (_response != null) tcs.SetResult(_response);
            else ResponseHandler += tcs.SetResult; //The event passes an object of type Response (derp) which is then assigned to the _response field.
            return tcs.Task;
        }
    }
Run Code Online (Sandbox Code Playgroud)


SLa*_*aks 13

它看起来像是_response你班上的一个领域.

_response从lambda 引用将this在闭包中捕获,并this._response在lambda执行时读取.

为了防止这种情况,您可以复制_response到本地变量并使用它.请注意,这将导致它使用当前_response而不是其最终值.