如何在C#中使用带有线程池的HttpClient PostAsync()?

 购物狂RZBZ_719 发布于 2023-02-07 13:37

我正在使用以下代码将图像发布到服务器.

var image= Image.FromFile(@"C:\Image.jpg");
Task upload = Upload(image);
upload.Wait();

public static async Task Upload(Image image)
{
    var uriBuilder = new UriBuilder
    {
        Host = "somewhere.net",
        Path = "/path/",
        Port = 443,
        Scheme = "https",
        Query = "process=false"
    };

    using (var client = new HttpClient())
    {
        client.DefaultRequestHeaders.Add("locale", "en_US");
        client.DefaultRequestHeaders.Add("country", "US");

        var content = ConvertToHttpContent(image);
        content.Headers.ContentType = MediaTypeHeaderValue.Parse("image/jpeg");

        using (var mpcontent = new MultipartFormDataContent("--myFakeDividerText--")
            {
                {content, "fakeImage", "myFakeImageName.jpg"}
            }
        )
        {
            using (
                var message = await client.PostAsync(uriBuilder.Uri, mpcontent))
            {
                var input = await message.Content.ReadAsStringAsync();
                return "nothing for now";
            }
        }
    }
}

我想修改此代码以运行多个线程.我之前使用过"ThreadPool.QueueUserWorkItem"并开始修改代码以利用它.

private void UseThreadPool()
{
    int minWorker, minIOC;
    ThreadPool.GetMinThreads(out minWorker, out minIOC);
    ThreadPool.SetMinThreads(1, minIOC);

    int maxWorker, maxIOC;
    ThreadPool.GetMaxThreads(out maxWorker, out maxIOC);
    ThreadPool.SetMinThreads(4, maxIOC);

    var events = new List();

    foreach (var image in ImageCollection)
    {
        var resetEvent = new ManualResetEvent(false);
        ThreadPool.QueueUserWorkItem(
            arg =>
            {
                var img = Image.FromFile(image.getPath());
                Task upload = Upload(img);
                upload.Wait();
                resetEvent.Set();
            });
        events.Add(resetEvent);

        if (events.Count <= 0) continue;

        foreach (ManualResetEvent e in events) e.WaitOne();
    }
}

问题是由于调用"upload.Wait()",一次只执行一个线程.所以我仍然按顺序执行每个线程.我不清楚如何将PostAsync与线程池一起使用.

如何通过调整上面的代码使用多个线程将图像发布到服务器?HttpClient PostAsync是最好的方法吗?

1 个回答
  • 我想修改此代码以运行多个线程.

    为什么?线程池应仅用于CPU绑定工作(当然还有I/O完成).

    您可以通过以下方式完成并发async:

    var tasks = ImageCollection.Select(image =>
    {
      var img = Image.FromFile(image.getPath());
      return Upload(img);
    });
    await Task.WhenAll(tasks);
    

    请注意,我删除了你的Wait.你应该避免使用WaitResult使用async任务; 使用await来代替.是的,这将导致async您通过代码增长,并且您应该使用async"一路".

    2023-02-07 13:39 回答
撰写答案
今天,你开发时遇到什么问题呢?
立即提问
热门标签
PHP1.CN | 中国最专业的PHP中文社区 | PNG素材下载 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有