Будет ли FromAsyncPattern утилизировать ресурсы, которые больше не используются? - PullRequest
1 голос
/ 16 сентября 2011

Будет ли FromAsyncPattern закрывать мой веб-ответ:

var o = Observable.Return(HttpWebRequest.Create("http://foo.com"))
                  .SelectMany(r => Observable.FromAsyncPattern<WebResponse>(
                      r.BeginGetResponse,
                      r.EndGetResponse)())
                  .Select(r => r.ContentLength);
// The response is now disposed

Или я должен сделать это вручную?

var o = Observable.Return(HttpWebRequest.Create("http://foo.com"))
                  .SelectMany(r => Observable.FromAsyncPattern<WebResponse>(
                      r.BeginGetResponse,
                      r.EndGetResponse)())
                  .Select(r => Tuple.Create(r, r.ContentLength))
                  .Do(t => t.Item1.Close())
                  .Select(t => t.Item2);

Если я должен сделать это вручную, есть ли лучший способ, чемэто?

Ответы [ 3 ]

4 голосов
/ 17 сентября 2011

Observable.Using может использоваться для этой цели как:

var o = Observable.Return(HttpWebRequest.Create("http://www.google.com"))
                  .SelectMany(r => Observable.FromAsyncPattern<WebResponse>(
                      r.BeginGetResponse,
                      r.EndGetResponse)())
                  .SelectMany(r =>
                  {
                      return Observable.Using( () => r, (resp) => Observable.Return(resp.ContentLength));
                  });
1 голос
/ 19 сентября 2011

Как бы чуть более чистая версия запроса Using была бы такой:

var o =
    from rq in Observable.Return(HttpWebRequest.Create("http://foo.com"))
    from cl in Observable.Using(() => rq.GetResponse(),
        rp => Observable.Return(rp.ContentLength))
    select cl;

Я бы предложил добавить Scheduler.ThreadPool как минимум к первому Return, чтобы сделать наблюдаемое выполненным в фоновом потоке- по умолчанию Scheduler.Immediate в противном случае.

1 голос
/ 16 сентября 2011

Я не верю, что FromAsyncPattern может закрыть ваши ресурсы, даже если бы захотел. У него недостаточно информации о том, как объект, для которого он выполняет асинхронные вызовы (в данном случае HttpWebRequest), или объект, возвращенный из асинхронных вызовов (в данном случае WebResponse), будут использоваться в другом месте, чтобы знать, когда он будет сохранен Dispose.

Тем не менее, вы все равно можете закрыть ресурсы вручную без дополнительных вызовов Do и Select. Просто измените Select в первом примере на:

.Select(r => { using (r) { return r.ContentLength; }});

Единственный Rx-оператор, который будет вызывать Dispose, о котором я знаю, это Observable.Using. Однако, исходя из его подписи, было не сразу очевидно, как или если это могло бы применяться здесь, поэтому я пошел с вышеупомянутым подходом.

...