I am getting this warning ("Implicity captured closure: this") from Resharper: does this mean that somehow this code is capturing the entire enclosing object?
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;
}
}
I'm not sure how or why it's doing so – the only variable it should be capturing is the TaskCompletionSource, which is intentional. Is this actually a problem and how would I go about solving it if it is?
EDIT: The warning is on the first lambda (the Timeout event).
Best Answer
It seems that the problem isn't the line I think it is.
The problem is that I have two lambdas referencing fields in the parent object: The compiler generates a class with two methods and a reference to the parent class (
this
).I think this would be a problem because the reference to
this
could potentially stay around in the TaskCompletionSource object, preventing it from being GCed. At least that's what I've found on this issue suggests.The generated class would look something like this (obviously names will be different and unpronounceable):
The reason the compiler does this is probably efficiency, I suppose, as the
TaskCompletionSource
is used by both lambdas; but now as long as a reference to one of those lambdas is still referenced the reference toRequest
object is also maintained.I'm still no closer to figuring out how to avoid this issue, though.
EDIT: I obviously didn't think through this when I was writing it. I solved the problem by changing the method like this: