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; } }
我不知道如何或为什么这样做 – 它应该捕获的唯一variables是TaskCompletionSource,这是故意的。 这实际上是一个问题,如果它是如何解决它?
编辑:警告是第一个lambda(超时事件)。
看来这个问题不是我认为的问题。
问题是我在父对象中有两个引用字段的lambdas:编译器用两个方法和一个对父类的引用( this
)生成一个类。
我认为这将是一个问题,因为这个引用可能会停留在TaskCompletionSource对象中,阻止它被GCed。 至less这就是我在这个问题上发现的结果。
生成的类看起来像这样(显然名称将是不同的和不可发音的):
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); } }
编译器这样做的原因可能是效率,我猜想, TaskCompletionSource
被两个lambda使用; 但是现在只要引用其中一个lambda仍然被引用,那么对Request
对象的引用也会被保留。
尽pipe如此,我仍然没有弄清楚如何避免这个问题。
编辑:我明显没有想到通过这个时候,我正在写它。 我通过改变这样的方法解决了这个问题:
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; } }
看起来_response
是你class上的一个领域。
引用lambda中的_response
会在闭包中捕获this
,并且在lambda执行时读取this._response
。
为了防止这种情况,您可以将_response
复制到一个局部variables,然后使用它。 请注意,这将导致它使用_response
的当前值而不是其最终值。
- ASP.net尝试将文件上载到Windows Server 2008 R2 Web服务器时出现“访问path被拒绝”错误
- 如何在.NET中使用真实文件进行集成testing?
- 如何增加ASP.NET中的最大上传文件大小?
- 从WinForms应用程序中删除ClickOnce
- 用.NET / C#应用程序自动更新的免费解决scheme?
- LINQ:何时使用SingleOrDefault与FirstOrDefault()与过滤标准
- 为什么List.Sort()是一个实例方法,但Array.Sort()是静态的?
- 获取Windows 8自动颜色主题的活动颜色
- System.Timers.Timer与System.Threading.Timer