C# 使用WebClient将同步下载转换为HttpClient

C# 使用WebClient将同步下载转换为HttpClient,c#,httpclient,webclient,C#,Httpclient,Webclient,我有一个WinForms应用程序,它可以创建多个对象,每个对象都有自己的WebClient,并在其构造函数上调用DownloadStringAsync。调用回调DownloadStringAsyncComplete时,将更新显示。 我想在这里保留的主要方面是能够同时执行多个请求,因为每个请求都需要几秒钟的时间。 如何使用HttpClient实现这一点? 我不能等待GetAsync,但是,我如何知道每个响应何时到达? 如果我等待GetAsync,那么它们将一个接一个地执行,整个过程将花费很长时间

我有一个WinForms应用程序,它可以创建多个对象,每个对象都有自己的WebClient,并在其构造函数上调用DownloadStringAsync。调用回调DownloadStringAsyncComplete时,将更新显示。 我想在这里保留的主要方面是能够同时执行多个请求,因为每个请求都需要几秒钟的时间。 如何使用HttpClient实现这一点? 我不能等待GetAsync,但是,我如何知道每个响应何时到达? 如果我等待GetAsync,那么它们将一个接一个地执行,整个过程将花费很长时间

using System;
using System.Collections.Generic;
using System.Windows.Forms;
using System.Net;

namespace RequestTest
{
    public partial class Form1 : Form
    {
        List<Requester> requesters;

        public Form1()
        {
            InitializeComponent();

            requesters = new List<Requester>();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            for (int i = 0; i < 20; i++)
            {
                requesters.Add(new Requester(this));
            }
        }

        public void SomeoneCompletedDownload()
        {
            textBox1.AppendText("sample text");
        }
    }

    public class Requester
    {
        Form1 caller;

        public Requester(Form1 _caller)
        {
            caller = _caller;

            var client = new WebClient();
            client.DownloadStringCompleted += DownloadCompleted;
            client.DownloadStringAsync(new Uri("some-url"));
        }

        private void DownloadCompleted(object sender, DownloadStringCompletedEventArgs e)
        {
            caller.SomeoneCompletedDownload();
        }
    }
}
使用系统;
使用System.Collections.Generic;
使用System.Windows.Forms;
Net系统;
命名空间请求测试
{
公共部分类Form1:Form
{
列出申请者;
公共表格1()
{
初始化组件();
请求者=新列表();
}
私有void Form1\u加载(对象发送方、事件参数e)
{
对于(int i=0;i<20;i++)
{
添加(新请求者(此));
}
}
public void SomeoneCompletedDownload()
{
textBox1.AppendText(“示例文本”);
}
}
公共类请求者
{
表格1主叫人;
公共请求者(Form1\u调用方)
{
调用者=_调用者;
var client=new WebClient();
client.DownloadStringCompleted+=下载完成;
DownloadStringAsync(新Uri(“某些url”);
}
私有void下载已完成(对象发送方,DownloadStringCompletedEventArgs e)
{
caller.SomeoneCompletedDownload();
}
}
}
好的,我找到了自己的答案。 我只是将请求转移到一个等待的方法

方法本身等待响应并调用回调

但是当调用该方法时,我并不等待它完成

using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Net;
using System.Net.Http;

namespace RequestTest
{
    public partial class Form1 : Form
    {
        List<Requester> requesters;

        DateTime start;
        int counter;

        public Form1()
        {
            InitializeComponent();

            requesters = new List<Requester>();
        }

        private async void button1_Click(object sender, EventArgs e)
        {
            start = DateTime.Now;

            for (int i = 0; i < 30; i++)
            {
                requesters.Add(new Requester(this, i + 1));

                // only one of the following 3 lines should be uncommented
                //requesters[i].RequestWeb(); // this uses the old WebClient (~ 12 sec)
                //await requesters[i].RequestHttp(); // this takes forever since requests are executed one at a time (~ 86 sec)
                _ = requesters[i].RequestHttp(); // <-- This is the way to go for my app. Dispatch the request and continue executing discarding the result. Callback is called in the same method. (~ 13 sec, consistent with option #1)
            }
        }

        public void SomeoneCompletedDownload(string page)
        {
            var elapsed = DateTime.Now - start;
            counter++;
            textBox1.AppendText($"#{counter}: Page {page} finished after {elapsed.TotalSeconds.ToString("N2")} seconds.\r\n");
        }
    }

    public class Requester
    {
        Form1 caller;
        string page;
        string url;

        public Requester(Form1 _caller, int _page)
        {
            caller = _caller;
            page = _page.ToString();

            url = "https://www.youtube.com/";
        }

        public void RequestWeb()
        {
            var client = new WebClient();
            client.DownloadStringCompleted += DownloadCompleted;
            client.DownloadStringAsync(new Uri(url));
        }

        public async Task RequestHttp()
        {
            var client = new HttpClient();
            var response = await client.GetAsync(url);
            caller.SomeoneCompletedDownload(page);
        }

        private void DownloadCompleted(object sender, DownloadStringCompletedEventArgs e)
        {
            caller.SomeoneCompletedDownload(page);
        }
    }
}
使用系统;
使用System.Collections.Generic;
使用System.Threading.Tasks;
使用System.Windows.Forms;
Net系统;
使用System.Net.Http;
命名空间请求测试
{
公共部分类Form1:Form
{
列出申请者;
日期时间开始;
整数计数器;
公共表格1()
{
初始化组件();
请求者=新列表();
}
私有异步无效按钮1\u单击(对象发送方,事件参数e)
{
start=DateTime.Now;
对于(int i=0;i<30;i++)
{
添加(新的请求者(这个,i+1));
//以下三行中只能有一行未注释
//请求者[i].RequestWeb();//这使用旧的WebClient(~12秒)
//等待请求者[i].RequestHttp();//由于请求一次执行一个请求(约86秒),这将花费很长时间
_=requesters[i].RequestHttp();//好的,我找到了自己的答案。
我只是将请求转移到一个等待的方法

方法本身等待响应并调用回调

但是当调用该方法时,我并不等待它完成

using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Net;
using System.Net.Http;

namespace RequestTest
{
    public partial class Form1 : Form
    {
        List<Requester> requesters;

        DateTime start;
        int counter;

        public Form1()
        {
            InitializeComponent();

            requesters = new List<Requester>();
        }

        private async void button1_Click(object sender, EventArgs e)
        {
            start = DateTime.Now;

            for (int i = 0; i < 30; i++)
            {
                requesters.Add(new Requester(this, i + 1));

                // only one of the following 3 lines should be uncommented
                //requesters[i].RequestWeb(); // this uses the old WebClient (~ 12 sec)
                //await requesters[i].RequestHttp(); // this takes forever since requests are executed one at a time (~ 86 sec)
                _ = requesters[i].RequestHttp(); // <-- This is the way to go for my app. Dispatch the request and continue executing discarding the result. Callback is called in the same method. (~ 13 sec, consistent with option #1)
            }
        }

        public void SomeoneCompletedDownload(string page)
        {
            var elapsed = DateTime.Now - start;
            counter++;
            textBox1.AppendText($"#{counter}: Page {page} finished after {elapsed.TotalSeconds.ToString("N2")} seconds.\r\n");
        }
    }

    public class Requester
    {
        Form1 caller;
        string page;
        string url;

        public Requester(Form1 _caller, int _page)
        {
            caller = _caller;
            page = _page.ToString();

            url = "https://www.youtube.com/";
        }

        public void RequestWeb()
        {
            var client = new WebClient();
            client.DownloadStringCompleted += DownloadCompleted;
            client.DownloadStringAsync(new Uri(url));
        }

        public async Task RequestHttp()
        {
            var client = new HttpClient();
            var response = await client.GetAsync(url);
            caller.SomeoneCompletedDownload(page);
        }

        private void DownloadCompleted(object sender, DownloadStringCompletedEventArgs e)
        {
            caller.SomeoneCompletedDownload(page);
        }
    }
}
使用系统;
使用System.Collections.Generic;
使用System.Threading.Tasks;
使用System.Windows.Forms;
Net系统;
使用System.Net.Http;
命名空间请求测试
{
公共部分类Form1:Form
{
列出申请者;
日期时间开始;
整数计数器;
公共表格1()
{
初始化组件();
请求者=新列表();
}
私有异步无效按钮1\u单击(对象发送方,事件参数e)
{
start=DateTime.Now;
对于(int i=0;i<30;i++)
{
添加(新的请求者(这个,i+1));
//以下三行中只能有一行未注释
//请求者[i].RequestWeb();//这使用旧的WebClient(~12秒)
//等待请求者[i].RequestHttp();//由于请求一次执行一个请求(约86秒),这将花费很长时间

_=请求者[i].RequestHttp();//这回答了你的问题吗?一架飞机从伦敦飞到纽约需要8小时……如果你有8架飞机,需要多少时间?……似乎你认为需要1小时……@Selvin确实需要更少的时间,因为大部分时间都花在服务器端。@Eldar不是真的。我的应用程序目前可以工作,但根据微软的说法ft,不应使用WebClient类,而应使用HttpClient。我正在尝试在我的应用程序中查看如何执行此操作。这是否回答了您的问题?一架飞机从伦敦飞往纽约需要8小时…如果您有8架飞机,需要多少时间?…似乎您认为需要1小时…@Selvin确实需要较少的时间,因为大部分时间都花在服务器端。@Eldar不是真的。我的应用程序目前可以工作,但根据Microsoft的规定,不应使用WebClient类,而应使用HttpClient。我正在尝试在我的应用程序中查看如何做到这一点。