反应式扩展清理
如果您有使用 rx 的长调用链,例如:
var responses = collectionOfHttpRequests.ToObservable()
.FromAsyncPattern(req.BeginGetResponse, req.EndGetResponse)
.Select(res => res.GetResponseBodyString()) // Extension method to get the body of the request
.Subscribe();
然后在操作完成之前调用 dispose,http 请求是否会被取消、关闭和正确处置,还是我必须以某种方式从方法链中选择 httprequests并单独处理它们?
我有一件事可以同时发生多个 http 请求,并且我需要能够取消(而不是忽略)其中一些/全部请求以节省网络流量。
If you have a long chain of calls using rx such as:
var responses = collectionOfHttpRequests.ToObservable()
.FromAsyncPattern(req.BeginGetResponse, req.EndGetResponse)
.Select(res => res.GetResponseBodyString()) // Extension method to get the body of the request
.Subscribe();
and then before the operation completes you call a dispose, will the http requests be cancelled, closed, and disposed of properly or do I have to somehow select the httprequests from the method chains and dispose of them individually?
I have a thing where one can have several http requests occurring at once and I need to be able to cancel (not ignore) some/all of them to save network traffic.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
当序列完成、错误或订阅被处理时,Rx 操作符链将自行清理。然而,每个操作员只会清理他们期望清理的内容。例如,
FromEvent
将取消订阅事件。就您而言,
Begin/End
异步模式,因此 Rx 无需取消任何内容。但是,您可以使用
Finally
调用HttpWebRequest.Abort
。The Rx operator chain will clean itself up when the sequence completes, errors or the subscription is disposed. However, each operator will only cleanup what they are expected to cleanup. For example,
FromEvent
will unsubscribe from the event.In your case, cancellation is not supported by the
Begin/End
asynchronous pattern, so there is nothing for Rx to cancel. You can, however, use
Finally
to callHttpWebRequest.Abort
.我不能承认理查德·萨莱的解决方案是可以接受的。如果您启动 100 个请求,而第二个请求因服务器不可用错误而失败(例如),则其余 98 个请求将被中止。第二个问题是 UI 将如何对这样的 observable 做出反应?太悲伤了。
请记住 Rx 设计指南的第 4.3 章 我希望通过 Observable.Using() 运算符表达 WebRequest observable。但WebRequest不是一次性的!所以我定义了 DisposableWebRequest:
然后我创建 WPF 窗口并在其上放置两个按钮(开始和停止)。
因此,让我们创建适当的请求可观察集合。
首先,定义 URL 的可观察创建函数:
在每个 url 上,我们应该创建 webrequest 可观察,因此:
另外定义两个对按钮“开始”/“停止”点击做出反应的事件可观察:
所以砖块已准备好,是时候组合它们了(我在 InitializeComponent() 之后的视图构造函数中执行此操作:
您可能想知道函数“HandleError()”。如果 EndGetResponse() 调用中发生异常(我关闭了网络连接来重现它)并且没有在 request observable 中捕获 - 它将导致 startMouseDown observable 崩溃。 HandleError 以静默方式捕获异常,执行提供的操作,并且不会为下一个观察者调用 OnError,而是调用 OnCompleted:
最后一个未解释的地方是方法 RefreshLabels,它更新 UI 控件:
I can't admit Richard Szalay's solution as acceptable. If you start 100 requests and second request failed with server unavailable error (for example) remaining 98 requests will be aborted. The second problem is how UI will react on such observable? Too sad.
Keeping in mind chapter 4.3 of Rx Design Guidelines I desired to express WebRequest observable via Observable.Using() operator. But WebRequest is not disposable! So I defined DisposableWebRequest:
Then I create WPF window and put two buttons on it (Start and Stop).
So, let's create proper requests observable collection.
At first, define URL's observable create function:
On every url we should create webrequest obervable, so:
In addition define two event observables which reacts on buttons "Start"/"Stop" clicks:
So bricks are ready, time to compose them (I do it in view constructor just after InitializeComponent()):
You may wonder on function "HandleError()". If exception occured in EndGetResponse() call (I turned off network connection to reproduce it) and not catched in request observable - it will crash the startMouseDown observable. HandleError catches exception silently, perfom provided action and instead of call OnError for next observer it calls OnCompleted:
The last unexplained place is method RefreshLabels, which updates UI controls: