我正在尝试使用Rx对Web端点进行完全异步读取。我以一种丑陋的方式使用这样的东西:
var reqUri = new Uri(string.Format("https://cds.cern.ch/record/{0}/export/xm?ln=en", docID));
var wr = WebRequest.CreateHttp(reqUri);
var s = Observable
.FromAsyncPattern<WebResponse>(
wr.BeginGetResponse,
wr.EndGetResponse)
.Invoke()
.Catch(Observable.Return<WebResponse>(null))
.Select(ExtractString)
.Select(ParseToMD);
ExtractString是一种阻止方法,可以打开流并将其读回。不过,我想把它做为异步,但为了做到这一点,我遇到了一些麻烦。我认为以下内容应该有效:
var s = Observable
.FromAsyncPattern<WebResponse>(
wr.BeginGetResponse,
wr.EndGetResponse)
.Invoke()
.SelectMany(resp => Observable.Using(() => resp.GetResponseStream(), strm => Observable.Return(strm)))
.SelectMany(resp => Observable.Using(() => new StreamReader(resp), strm => Observable.Return(strm)))
.SelectMany(strm => Observable.FromAsync(tkn => strm.ReadToEndAsync()))
.Select(ParseToMD);
而且,如果我在那里的某个点放置一个断点,有时候它会起作用。其他时候它只是挂起。所以,我有两个问题。首先,这是做这样的事情的正确方法吗?第二,调试这样的东西的最佳方法是什么?是否有一些我可以观看的跟踪显示事件通过系统?我刚刚在lambda函数中设置了断点。
ParseMD函数只是将字符串转换为一类数据。
答案 0 :(得分:0)
您可以使用Spy method I present in this question跟踪流生存期。
你离这儿不远 - 我认为问题可能是你对Observable.Using
有点过分热心。 Observable.Return
可以完成导致竞争条件,其中可以在流阅读器完成之前处理响应流。我认为这可能会更可靠:
var reqUri = new Uri(
string.Format("https://cds.cern.ch/record/{0}/export/xm?ln=en", docId));
var s = Observable.FromAsyncPattern<WebResponse>(
wr.BeginGetResponse,
wr.EndGetResponse)
.Invoke()
.Select(response => response.GetResponseStream())
.SelectMany(stream =>
Observable.Using( () => new StreamReader(stream),
reader => Observable.StartAsync(reader.ReadToEndAsync)))
.Select(ParseToMD);