FromAsyncPattern是否会处理不再使用的资源?

时间:2011-09-16 12:14:50

标签: c# c#-4.0 resources system.reactive

FromAsyncPattern会关闭我的webresponse:

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 个答案:

答案 0 :(得分:4)

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 :(得分:1)

我不相信FromAsyncPattern会关闭你的资源,即使它想要。它没有足够的信息来说明它进行异步调用的对象(在本例中为HttpWebRequest)或异步调用返回的对象(本例中为WebResponse)将如何在其他地方使用以了解它何时保存到Dispose

也就是说,您仍然可以手动关闭资源,而无需额外的DoSelect来电。只需将第一个示例中的Select更改为:

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

我唯一会调用Dispose的Rx运算符是Observable.Using。但是,根据它的签名,它是如何或是否适用于此处并不是很明显,所以我采用了上述方法。

答案 2 :(得分:1)

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,以便在后台线程上执行observable - 否则默认为Scheduler.Immediate