Resharper: неявно захваченное закрытие: это
Я получаю это предупреждение ("Implicity captured closure: this") от Resharper: означает ли это, что каким-то образом этот код захватывает весь охватывающий объект?
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;
}
}
Я не уверен, как и почему это происходит - единственная переменная, которую он должен захватывать, - это TaskCompletionSource, который является преднамеренным. Это действительно проблема, и как бы я ее решил, если это так?
EDIT: предупреждение находится на первой лямбде (событие тайм-аута).
2 ответа:
кажется, что проблема не в линии, я думаю.
проблема в том, что у меня есть два лямбда-поля ссылки в Родительском объекте: компилятор генерирует класс с двумя методами и ссылкой на родительский класс (
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); } }
причина, по которой компилятор делает это, вероятно, эффективность, я полагаю, как
TaskCompletionSource
используется обеими лямбдами; но теперь, пока ссылка на одну из этих лямбд все еще ссылается на ссылку на
похоже
_response
поля в вашем классе.ссылка
_response
от лямбда захватаthis
в закрытии, и будет читатьthis._response
когда лямбда-выражения.чтобы предотвратить это, вы можете скопировать
_response
к локальной переменной и использовать ее вместо этого. Обратите внимание, что это заставит его использовать настоящее стоимостью_response
, а не его конечной стоимости.