Ответ 1
Кажется, что проблема не в том, что я думаю.
Проблема заключается в том, что у меня есть два поля привязки 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);
}
}
Причина, по которой компилятор делает это, вероятно, является эффективностью, я полагаю, поскольку TaskCompletionSource
используется как lambdas; но теперь, пока ссылка на один из этих lambdas по-прежнему ссылается на ссылку на объект Request
, также поддерживается.
Я все еще не ближе к выяснению, как избежать этой проблемы.
EDIT: Я, очевидно, не думал об этом, когда писал. Я решил проблему, изменив метод следующим образом:
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;
}
}