WebClient does not support concurrent I/O operations
Asked Answered
P

6

24

How can I get this error from with in the DownloadStringCompleted Event? Doesn't that mean, it's finished? Is there another event I can fire this from?

I get this error extremely rarely, but once in a while it will happen on my WP7 phone. I have a web client that I fire over and over, and I fire it again from the completed event. Is this happening because there is still some stale connection open? Is there a way to prevent this 100%?

I have checked to see if there is a chance for the thread to walk over itself, but it is only fired from within the completed event.

How can I be sure, when the complete event is fired, the client is no longer isBusy? One suggestion was to add a while with a thread sleep while the client is busy.

Some pseudo code.

var client = new WebClient("URL 1");
client.CompletedEvent += CompletedEvent;
client.downloadasync();

void CompletedEvent(){
Dosomestuff;
client.downloadasync(); //This is where we break.
}
Prosthodontics answered 19/3, 2012 at 4:39 Comment(0)
A
20

The WebClient only supports a single operations, it cannot download multiple files. You haven't shown your code, but my guess is that you are somehow firing a new request before the old is completed. My bet is that WebClient.IsBusy is true when you attempt to perform another fetch.

See the following thread:

wb.DownloadFileAsync throw "WebClient does not support concurrent I/O operations." exception

Archdiocese answered 19/3, 2012 at 6:19 Comment(4)
My point is I never call downloadasync unless i'm in the completed event. Shouldn't the connection be closed and client free if I'm in that event? If this isn't the case, how can I avoid it other than to use IsBusy?Prosthodontics
Yes, this thread is telling me to do exactly what am I doing now and I am getting the error. I will add some more information above.Prosthodontics
Just to save anyone the bother, that answer posted above just links to here: #2042758Lyndes
I have the same issue and I am waiting to have client.IsBusy = false before puting the client back in the BlockingCollectionPilsner
O
11

Instead of using WebClient use HttpClient to do parallel HTTP calls. Below code shows how to download files.

        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);
                }

            }
        });
Overmaster answered 25/9, 2017 at 11:47 Comment(1)
This is the only post around that actually addresses this problem. Kick ass thanks man. +1Tricorn
P
10

The only answer is to create a new webclient within the scope of the Completed Event. You can't set it to new since webclient is readonly. Creating a new client is the only solution. This allows the old client to complete in the background. This does have slight memory implications since you are creating a new instance instead of reusing an old. But the garbage collector should keep it clean if your scope is setup right.

Prosthodontics answered 3/4, 2012 at 17:45 Comment(0)
G
0

The solution, I found is to use multiple WebClient objects, so to modify your pseudocode example; try

var client = new WebClient("URL 1");
client.CompletedEvent += CompletedEvent;
client.downloadasync();

void CompletedEvent(){
Dosomestuff;
var client2 = new WebClient();
client2.downloadasync(); 
}
Going answered 22/9, 2017 at 16:8 Comment(0)
N
0

Create a new Web Client for each new request. Don't reuse an existing Web Client instance.

This allows the first request to complete before starting the new one. This is a standard way of creating new requests.

Neurogram answered 28/1, 2022 at 20:19 Comment(0)
H
0
        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
                }
            }
        }
   
Hydrastinine answered 30/11, 2022 at 21:26 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.