Multiple HTTP Requests in WinRT / Win8

2019-05-29 12:43发布

问题:

Is it possible to send more than two HTTP requests concurrently in WinRT? I'm trying to load multiple JSON documents from a server and HttpWebRequest fails to respond after the second call. Here is a sample snippet that illustrates this:

protected async override void OnNavigatedTo(NavigationEventArgs e)
{
    const string url = "http://www.bom.gov.au/fwo/IDV60901/IDV60901.94868.json";
    const int iterations = 3;

    var tasks = new List<Task>();
    var ticks = DateTime.Now.Ticks;

    for (var i = 0; i < iterations; i++)
    {
        // Create unique URL by appending a generated number.
        var uniqueUrl = string.Format("{0}?v={1}", url, (i + ticks));

        // Create the request.
        var request = WebRequest.CreateHttp(uniqueUrl);

        // Create the async task and store it for later.
        var task = request.GetResponseAsync();

        tasks.Add(task);
    }

    // Await all tasks in collection.
    await Task.WhenAll(tasks);



    Debugger.Break(); // <----- This will never break when iterations > 2
}

Put this code in a blank MainPage.xaml.cs and play around with the iterations value. If you set it to 2, then it works. Anything above that, it will fail.

NOTE :: Do not use Fiddler when testing this. Fiddler does something funny and it allows all these connections to go through. I don't know how nor why. You can test this yourself. If you run the code above with fiddler open, then success.

NOTE :: This is not real code. I'm only using this example to illustrate the issue.

回答1:

I haven't tried using the WebClient API in WinRT, I've only used the HttpClient API (which I'm using quite extensively in my application).

This code works:

const string url = "http://www.bom.gov.au/fwo/IDV60901/IDV60901.94868.json";
const int iterations = 10;

var tasks = new List<Task<HttpResponseMessage>>();
var ticks = DateTime.Now.Ticks;

for (var i = 0; i < iterations; i++)
{
    // Create unique URL by appending a generated number.
    var uniqueUrl = string.Format("{0}?v={1}", url, (i + ticks));

    var handler = new HttpClientHandler();

    var client = new HttpClient(handler)
                        {
                            BaseAddress = new Uri(uniqueUrl)
                        };

    var task = client.GetAsync(client.BaseAddress);

    tasks.Add(task);
}

// Await all tasks in collection.
await Task.WhenAll(tasks);

It is a bit more tedious to get out the response body though as you need to do an async read of all the responses like so:

var responseTasks = tasks.Select(task => task.Result.Content.ReadAsStringAsync());

await Task.WhenAll(responseTasks);

Then you can iterate through the responseTask objects and take their result.