首页 > 解决方案 > 在 C# 中异步使用 Web API

问题描述

我有一个控制台应用程序,它作为调度程序运行,同样使用一个 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(任务并行库)。我应该在上面的代码中执行哪些更改以使其异步工作。

请帮忙提供样品。

标签: c#multithreadingasynchronoustask-parallel-librarythreadpool

解决方案


您需要创建 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 async;static async Task Main(string[] args)

请注意,这DataSet不是线程安全的。因此,我不建议您使用此方法更改该类。

如果您在运行 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);
}

推荐阅读