WebClient不支持并发I/O操作

本文关键字:操作 不支持 并发 WebClient | 更新日期: 2023-09-27 18:28:09

如何在DownloadStringCompleted事件中从中获取此错误?这不意味着,它结束了吗?还有其他事件可以触发吗?

我很少遇到这种错误,但偶尔会在我的WP7手机上发生。我有一个web客户端,我一遍又一遍地启动它,并从完成的事件中再次启动它。发生这种情况是因为仍然有一些陈旧的连接打开吗?有没有办法100%防止这种情况发生?

我已经检查了线程是否有机会遍历自己,但它只是从已完成的事件中启动的。

我如何确定,当整个事件被激发时,客户端不再繁忙?一个建议是在客户端繁忙时添加一个线程睡眠时间。

一些伪代码。

var client = new WebClient("URL 1");
client.CompletedEvent += CompletedEvent;
client.downloadasync();
void CompletedEvent(){
Dosomestuff;
client.downloadasync(); //This is where we break.
}

WebClient不支持并发I/O操作

WebClient只支持单个操作,不能下载多个文件。您还没有显示您的代码,但我猜测您在旧请求完成之前以某种方式启动了一个新请求。我敢打赌,当您尝试执行另一次提取时,WebClient.IsBusy为真。

请参阅以下线程:

wb.DownloadFileAsync抛出";WebClient不支持并发I/O操作"异常

唯一的答案是在Completed Event的范围内创建一个新的web客户端。您不能将其设置为new,因为web客户端是只读的。创建一个新客户端是唯一的解决方案。这允许旧客户端在后台完成。这确实有轻微的内存影响,因为您正在创建一个新实例,而不是重用一个旧实例。但是,如果您的作用域设置正确,垃圾收集器应该保持干净。

不要使用WebClient,而是使用HttpClient进行并行HTTP调用。下面的代码显示了如何下载文件。

        HttpClient httpClient = new HttpClient();
        var documentList=_documentManager.GetAllDocuments();
        documentList.AsParallel().ForAll(doc =>
        {
            var responseResult= httpClient.GetAsync(doc.FileURLPath);
            using (var memStream = responseResult.Result.Content.ReadAsStreamAsync().Result)
            {
                using (var fileStream =File.Create($"{filePath}''{doc.FileName}"))
                {
                    memStream.CopyTo(fileStream);
                }
            }
        });

我发现的解决方案是使用多个WebClient对象,以便修改您的伪代码示例;尝试

var client = new WebClient("URL 1");
client.CompletedEvent += CompletedEvent;
client.downloadasync();
void CompletedEvent(){
Dosomestuff;
var client2 = new WebClient();
client2.downloadasync(); 
}

为每个新请求创建一个新的Web客户端。不要重复使用现有的Web客户端实例。

这允许在开始新的请求之前完成第一个请求。这是创建新请求的标准方式。

        private async Void SyncParcelStatus(List<string> Urls)
        {                               
                try
                {                    
                    foreach (var URL in WebhookUrls)
                    {                        
                            Task.Factory.StartNew(() => AsyncDownLoad(URL));                       
                    }
                }
                catch (Exception ex)
                {
                    //log Exception 
                }
        }
        private async void AsyncDownLoad(string URL)
        {
            using (WebClient myWebClient = new WebClient())
            {
                try
                {
                    Uri StringToUri = new Uri(URL);
                    myWebClient.DownloadStringAsync(StringToUri);
                }
                catch (Exception ex)
                {
                    //log Exception
                }
            }
        }