Multiple WebClients not working?

2019-02-23 16:58发布

I am trying to download three files with three separate WebClients. I use this:

    void client1_OpenReadCompleted(object sender, OpenReadCompletedEventArgs e)
    {
        MessageBox.Show("CLIENT1");
    }

    void client2_OpenReadCompleted(object sender, OpenReadCompletedEventArgs e)
    {
        MessageBox.Show("CLIENT2");
    }

    void client3_OpenReadCompleted(object sender, OpenReadCompletedEventArgs e)
    {
        MessageBox.Show("CLIENT3");
    }

    private void mwindow_Loaded(object sender, RoutedEventArgs e)
    {
        string rand = new Random().Next().ToString();
        WebClient client1 = new WebClient();
        client1.OpenReadCompleted += client1_OpenReadCompleted;
        client1.OpenReadAsync(new Uri("http://www.example.com/file.exe?r=" + rand));

        WebClient client2 = new WebClient();
        client2.OpenReadCompleted += client2_OpenReadCompleted;
        client2.OpenReadAsync(new Uri("http://www.example.com/file.exe?r=" + rand));

        WebClient client3 = new WebClient();
        client3.OpenReadCompleted += client3_OpenReadCompleted;
        client3.OpenReadAsync(new Uri("http://www.example.com/file.exe?r=" + rand));
    }

When using this, no matter what I do, only two out of the three WebClients will finish. Using this code, I get two message boxes "CLIENT1", and "CLIENT2", but "CLIENT3" never appears. No exceptions are thrown or anything. Nothing happens. If I reverse the order of the WebClients, client3 and client2 work but not client1. I have tried changing the code to make the WebClients download one at a time instead of asynchronously:

        WebClient client1 = new WebClient();
        Stream str1 = client1.OpenRead(new Uri("http://www.example.com/file.exe?r=" + rand));
        MessageBox.Show("CLIENT1");

        WebClient client2 = new WebClient();
        Stream str2 = client2.OpenRead(new Uri("http://www.example.com/file.exe?r=" + rand));
        MessageBox.Show("CLIENT2");

        WebClient client3 = new WebClient();
        Stream str3 = client3.OpenRead(new Uri("http://www.example.com/file.exe?r=" + rand));
        MessageBox.Show("CLIENT3");

However, the program freezes on the Stream str3 = client3.OpenRead(new Uri("http://www.example.com/file.exe?r=" + rand)); line. Having client1 download all the files synchronously instead of creating multiple WebClients also freezes on the third file.

1条回答
Luminary・发光体
2楼-- · 2019-02-23 17:32

I think what you're experiencing is a combination of two issues. The first one being that the number of concurrent WebRequest connections is limited to 2 by default. You can change that by creating a class derived from WebClient and overriding the GetWebRequest method like so:

public class ExtendedWebClient : WebClient
{
    /// <summary>
    /// Gets or sets the maximum number of concurrent connections (default is 2).
    /// </summary>
    public int ConnectionLimit { get; set; }

    /// <summary>
    /// Creates a new instance of ExtendedWebClient.
    /// </summary>
    public ExtendedWebClient()
    {
        this.ConnectionLimit = 2;
    }

    /// <summary>
    /// Creates the request for this client and sets connection defaults.
    /// </summary>
    protected override WebRequest GetWebRequest(Uri address)
    {
        var request = base.GetWebRequest(address) as HttpWebRequest;

        if (request != null)
        {
            request.ServicePoint.ConnectionLimit = this.ConnectionLimit;
        }

        return request;
    }
}

The second problem I see is that you're not closing/disposing of the Stream returned when you call OpenRead, so it would appear that the two requests do not complete until such time when the Garbage Collector decides to kick in and close those streams for you.

查看更多
登录 后发表回答