繁体   English   中英

具有Reactive Extensions的并行HttpWebRequests

[英]Parallel HttpWebRequests with Reactive Extensions

我有一个“图像”类,它有三个属性:Url,Id,Content。 我有10个这样的图像列表。 这是一个silverlight应用程序。

我想创建一个方法:

IObservable<Image> DownloadImages(List<Image> imagesToDownload)
{
     //start downloading all images in imagesToDownload
     //OnImageDownloaded: 
                          image.Content = webResponse.Content
                          yield image

}

此方法开始并行下载所有10个图像。 然后,当每次下载完成时,它将Image.Content设置为该下载的WebResponse.Content。

结果应该是每个下载图像的IObservable流。

我是RX的初学者,我认为我想要的东西可以通过ForkJoin实现,但那是在我不想使用的反应式扩展dll的实验版本中。

另外,我真的不喜欢下载回调计数以检测所有图像已被下载然后调用onCompleted()。

对我来说似乎没有Rx精神。

我也发布了迄今为止我编码的解决方案,虽然我不喜欢我的解决方案,因为它长/丑并使用计数器。

     return Observable.Create((IObserver<Attachment> observer) =>
         {
             int downloadCount = attachmentsToBeDownloaded.Count;
                foreach (var attachment in attachmentsToBeDownloaded)
                        {
                            Action<Attachment> action = attachmentDDD =>
                            this.BeginDownloadAttachment2(attachment).Subscribe(imageDownloadWebResponse =>
                                {
                                    try
                                    {
                                        using (Stream stream = imageDownloadWebResponse.GetResponseStream())
                                        {
                                            attachment.FileContent = stream.ReadToEnd();
                                        } 
                                        observer.OnNext(attachmentDDD);

                                        lock (downloadCountLocker)
                                        {
                                            downloadCount--;
                                            if (downloadCount == 0)
                                            {
                                                observer.OnCompleted();
                                            }
                                        }
                                    } catch (Exception ex)
                                    {
                                        observer.OnError(ex);
                                    }
                                });
                            action.Invoke(attachment);
                        }

                        return () => { }; //do nothing when subscriber disposes subscription
                    });
            }

好吧,我确实根据Jim的回答管理它以使其最终工作。

    var obs = from image in attachmentsToBeDownloaded.ToObservable()
               from webResponse in this.BeginDownloadAttachment2(image).ObserveOn(Scheduler.ThreadPool)
               from responseStream in Observable.Using(webResponse.GetResponseStream, Observable.Return)
               let newImage = setAttachmentValue(image, responseStream.ReadToEnd())
               select newImage;

setAttachmentValue只需要``image.Content = bytes; 返回图像;

BeginDownloadAttachment2代码:

        private IObservable<WebResponse> BeginDownloadAttachment2(Attachment attachment)
    {
        Uri requestUri = new Uri(this.DownloadLinkBaseUrl + attachment.Id.ToString();
        WebRequest imageDownloadWebRequest = HttpWebRequest.Create(requestUri);
        IObservable<WebResponse> imageDownloadObservable = Observable.FromAsyncPattern<WebResponse>(imageDownloadWebRequest.BeginGetResponse, imageDownloadWebRequest.EndGetResponse)();

        return imageDownloadObservable;
    }

我们如何简化这一点。 拍摄图像列表并将其转换为可观察的图像。 接下来,考虑使用Observable.FromAsyncPattern来管理服务请求。 最后使用SelectMany来协调请求和响应。 我在这里对你如何获取文件流做了一些假设。 基本上,如果您可以将BeginInvoke / EndInvoke委托传递到FromAsyncPattern以获取服务请求,那么您很好。

var svcObs = Observable.FromAsyncPattern<Stream>(this.BeginDownloadAttachment2, This.EndDownloadAttchment2);

var obs = from image in imagesToDownload.ToObservable()
          from responseStream in svcObs(image)
          .ObserveOnDispatcher()
          .Do(response => image.FileContent = response.ReadToEnd())
          select image;
return obs;

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM