在 C# 中异步使用 Web API

Consuming Web API asynchronously in C#

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

  1. 将文件发布到 API - 我正在将一些文件发送到 API 以获取 文件中的一些信息。
  2. 从 API- 我收到回复的地方获得回复 从 API 我之前已经发送到 API。

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

因此下次调度程序运行时,它将 post 更多文件 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;

            }
        }
    }

这里所有的进程都是同步的,导致时间太长。

我想以异步方式进行 posting 处理和获取响应。 post将多个文件放在一起以及并行获取多个文件的响应

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

请帮忙提供样品。

您需要 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。因此,我不建议您使用此方法更改 class。

如果您不介意在 运行 Getresponse 之前等待您的 post,您还可以添加额外的并行化:

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);
}