Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to 'await' a WebClient.UploadStringAsync request?

The async pattern seems to be call an asynchronous, then yield control after awaiting a result, which makes a lot of sense.

However the WebClient class UploadStringAsync method does not return a Task, instead it return void and so cannot be awaited. Instead an event handler can be defined. e.g.

public async Task FlushQueue() {
    attempt = 0;
    WebClient wc = new WebClient();
    while ((queue.Count > 0) && (attempt < ALLOWED_ATTEMPTS)) {

        // Copy 10 items from queue and put into buffer ...
        ...
        wc.UploadStringCompleted += (s, e) => {
            // if response 200 
            // Remove 10 sent items from queue
            // else attempt++ 
        };
        wc.UploadStringAsync("http://example.com/blah", "POST", buffer);

        // In an ideal world we could call UploadStringAsync like,
        // var response = await wc.UploadStringAsync("http://example.com/blah", "POST", buffer);
    }
}

However, this does not await a response and instead quickly rattles through lauching the maximum number of web requests.

Is there a way to yield flow back outside of FlushQueue until the event handler callback is executed?

Edit: This is for a Windows Phone 7.5 project.

like image 224
Brendan Avatar asked May 03 '13 12:05

Brendan


1 Answers

You need to use UploadStringTaskAsync, which returns a Task<string>.

The async suffixes on pre-4.5 WebClient methods are unfortunate as they don't match the TAP signatures you'd expect. In general, in that situation it's recommended that API designers use TaskAsync instead of a Async as a suffix - which is exactly what WebClient did... hence DownloadStringTaskAsync etc.

You might also want to consider using HttpClient instead of WebClient.

like image 182
Jon Skeet Avatar answered Sep 27 '22 17:09

Jon Skeet