使用 Web 客户端接收参数异常
我正在使用反应式扩展,以便使用 Windows Phone 上的 WebClient 轻松下载网页。 当我运行以下代码时,我在 Subscribe 调用中收到 ArgumentExceptoin。
参数名称:{0}
参数名称:类型
public IObservable<DownloadStringCompletedEventArgs> StartRequest(string uri)
{
var _browser = new WebClient();
var obs = Observable.FromEvent<DownloadStringCompletedEventHandler,
DownloadStringCompletedEventArgs>(
h => _browser.DownloadStringCompleted += h,
h => _browser.DownloadStringCompleted -= h)
.Where(e => !e.Cancelled)
.Retry(3)
.SelectMany(
e => (e.Error == null && !string.IsNullOrEmpty(e.Result))
? Observable.Return(e)
: Observable.Throw<DownloadStringCompletedEventArgs>(e.Error))
.Take(1);
_browser.DownloadStringAsync(new Uri(uri));
return obs;
}
var obs = StartRequest("http://www.google.com");
obs.Subscribe(
x => Console.WriteLine(x.Result)
);
I am working with the Reactive Extensions, to easy download webpages with the WebClient on Windows Phone.
When I run the following code, I get an ArgumentExceptoin on the Subscribe call.
Parameter name: {0}
Parameter name: type
public IObservable<DownloadStringCompletedEventArgs> StartRequest(string uri)
{
var _browser = new WebClient();
var obs = Observable.FromEvent<DownloadStringCompletedEventHandler,
DownloadStringCompletedEventArgs>(
h => _browser.DownloadStringCompleted += h,
h => _browser.DownloadStringCompleted -= h)
.Where(e => !e.Cancelled)
.Retry(3)
.SelectMany(
e => (e.Error == null && !string.IsNullOrEmpty(e.Result))
? Observable.Return(e)
: Observable.Throw<DownloadStringCompletedEventArgs>(e.Error))
.Take(1);
_browser.DownloadStringAsync(new Uri(uri));
return obs;
}
var obs = StartRequest("http://www.google.com");
obs.Subscribe(
x => Console.WriteLine(x.Result)
);
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
您的问题是您使用的是
FromEvent
扩展,而不是FromEventPattern
扩展。前者适用于非标准事件,后者适用于遵循“sender/eventargs”模式的事件。
也就是说,您的可观察值仍然存在一些问题。
WebClient
的实例永远不会被释放。你应该做当然会发生这种情况,但因为你正在使用可观察的你需要
使用
Using
扩展方法。在
Take(1)
之前放置Where
可能意味着您的可观察值永远不会结束。
重试
也不会为您做正确的事情。如果“DownloadStringCompleted” observable 有错误然后重试
将重新附加到事件,但事件将永远不会返回新的
值,因为您不会再次调用
DownloadStringAsync
。您想要对这种可观察量做的是让它在每次新观察者订阅时重新执行网络调用,但是,当共享订阅时(例如,如果可观察量已发布),那么您不希望网络调用重新执行。你有点想鱼与熊掌兼得。
操作方法如下:
现在您可以这样调用它:
请注意,
Retry
现在位于它应该所属的请求方法之外(除非您添加retry
参数)到方法调用)。Your issue is that you're using the
FromEvent
extension rather than theFromEventPattern
extension.The former is for non-standard events and the latter for those that follow the "sender/eventargs" pattern.
That said, you still have a few more issues with your observable.
The instance of
WebClient
is never disposed of. You should makesure that happens, but because you're using an observable you need to
use the
Using
extension method.Putting a
Where
before theTake(1)
may mean that your observablewill never end.
The
Retry
is also not going to do the right thing for you. If the"DownloadStringCompleted" observable has an error then retrying it
will re-attach to the event, but the event will never return a new
value because you're not calling
DownloadStringAsync
again.What you want to do with this kind of observable is make it re-execute the web call every time a new observer subscribes, but, when a subscription is shared (if the observable is published, for example) then you don't want the web call to re-execute. You kind of want to have your cake and eat it too.
Here's how to do it:
Now you can call it like this:
Notice that the
Retry
is now outside of the request method where it should belong (unless you add aretry
argument to the method call).您不能将 Retry 与 FromEvent 结合使用,因为 FromEvent 是一个热门可观察对象 - 您只会获得 3 次相同的结果。修复现有代码的最简单方法是通过 Observable.Defer:
Defer 意味着不是立即创建 WebClient,而是为每个 Subscribe() 的 Observable 的人创建它,这是重试所需的。
You can't use Retry with FromEvent, because FromEvent is a hot observable - you'll just get the same result 3 times. The easiest way to fix your existing code is via Observable.Defer:
Defer means that instead of WebClient being created immediately, it will be created for everyone who Subscribe()'s to the Observable, which is what is required for Retry.