【问题标题】:Consuming Web API asynchronously in C#在 C# 中异步使用 Web API
【发布时间】:2018-08-08 15:43:01
【问题描述】:

我有一个控制台应用程序,它作为调度程序运行,同样使用一个 Web API,并且有两个部分,如下所述

  1. 将文件发布到 API - 我将一些文件发送到 API 以获取 文件中的一些信息。
  2. 从 API 获取响应 - 我接收响应的位置 来自我之前已经发送到 API 的 API。

所以流程如下。当调度程序最初运行时,我将向 API 发送一些文件(例如 A、B 和 C)。 API 会花一些时间来处理文件。

所以下次调度程序运行时,它会发布更多文件 D、E、F 等,并尝试获取 A、B、C 的响应

代码骨架如下

 static void Main(string[] args)
        {                               
            //"starting Posting files to API";
            PostDatas(ds);                

            //"Getting Response from the API";
            GetResponseXML(ds);               

        }
        public static void PostDatas(DataSet ds)
        {
            var client = new HttpClient();
            foreach (DataRow dr in ds.Tables[0].Rows)
            {
                //post the files 
                var response = client.PostAsync(URL, ReqClass, bsonFormatter).Result;

            }
        }
        public static void GetResponseXML(DataSet ds)
        {
            var clientResponse = new HttpClient();
            foreach (DataRow dr in ds.Tables[1].Rows)
            {
                //get the response.
                var response = clientResponse.PostAsync(URL,ReqClass, bsonFormatter).Result;

            }
        }
    }

这里所有的过程都是同步的,这导致了太多的时间。

我想进行发布过程并以异步方式获得响应。将多个文件一起发布并同时获得多个文件的响应

我怎样才能做到这一点?使用线程概念或使用异步和等待概念或 TPL(任务并行库)。我应该在上面的代码中执行哪些更改以使其异步工作。

请帮助提供样品。

【问题讨论】:

  • @Athul 删除对.Result.Wait() 的所有调用,并改用await。将使用HttpClient 的任何方法的签名更改为async Task
  • 这样可以实现并行处理吗? @Panagiotis Kanavos
  • @Liam : 怎么会导致死锁?

标签: c# multithreading asynchronous task-parallel-library threadpool


【解决方案1】:

你需要create an async version of your Main然后并行调用每个方法,然后await结果。我在这里阻止了您的void Main,因为我认为这就是您想要的?你可以在这里添加一个额外的线程池线程,但我怀疑你会从中获得很多好处。下面我只做了一种方法,另一种基本相同:

static void Main(string[] args)
{
    MainAsync(args).GetAwaiter().GetResult();
}


static async Task MainAsync(string[] args)
{
    DataSet ds = new DataSet();
    /*logic for getting dataset values.table0 contains posting file details
    and Table1 contains details of files which need response*/


    //"starting Posting files to API";
    await PostDatas(ds);
    //"Ending Posting files to API";

    //"Getting Response from the API";
    await GetResponseXML(ds);
    //"Ending Getting Response from the API";

}
public async static Task PostDatas(DataSet ds)
{
    var client = new HttpClient();
    List<Task<HttpResponseMessage>> tasks = new List<Task<HttpResponseMessage>>();
    foreach (DataRow dr in ds.Tables[0].Rows)
    {

        //post the files 
        tasks.Add(client.PostAsync(URL, ReqClass, bsonFormatter));

    }

    await Task.whenAll(tasks);
    foreach(var response in tasks)
    {
         //you can access Result here because you've awaited 
         //the result of the async call above
         HttpResponseMessage message = response.Result;
         //etc.

    }
}

C# 7.0 中,您可以取消 .GetAwaiter().GetResult(); 并声明您的 Main asyncstatic async Task Main(string[] args)

请注意DataSet is not threadsafe。因此,我不建议您使用此方法更改该类。

如果您不想在运行 Getresponse 之前等待您的帖子,您还可以添加额外的 parralisation:

static async Task MainAsync(string[] args)
{
    DataSet ds = new DataSet();
    /*logic for getting dataset values.table0 contains posting file details
    and Table1 contains details of files which need response*/

    List<Task> tasks = new List<Task>(2);
    //"starting Posting files to API";
    tasks.Add(PostDatas(ds));
    //"Ending Posting files to API";

    //"Getting Response from the API";
    tasks.Add(GetResponseXML(ds));
    //"Ending Getting Response from the API";

    await Task.WhenAll(tasks);
}

【讨论】:

猜你喜欢
  • 2017-01-11
  • 2015-09-01
  • 1970-01-01
  • 2021-08-16
  • 2019-08-19
  • 2021-04-05
  • 2011-10-03
  • 1970-01-01
  • 2017-07-19
相关资源
最近更新 更多