c# - 在 C# 中异步使用 Web API
问题描述
我有一个控制台应用程序,它作为调度程序运行,同样使用一个 Web API,并且有两个部分,如下所述
- 将文件发布到 API - 我将一些文件发送到 API 以从文件中获取一些信息。
- 从 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(任务并行库)。我应该在上面的代码中执行哪些更改以使其异步工作。
请帮忙提供样品。
解决方案
您需要创建 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);
}
推荐阅读
- python - 如何解析包含多个对象的单行 json 文件
- iot - IoT 代理配置
- python - 是否可以循环 10^8 种可能性来确定正确答案?
- java - 配置问题:找不到 XML 模式命名空间的 Spring NamespaceHandler
- node.js - 为 Node 模块导入 TS 类型
- angularjs - 带有引导崩溃的嵌套 ng-repeats,$index 和 ng-init 的问题
- javascript - 复制到剪贴板时如何添加新行
- javascript - 我想在 Object 中返回异步函数的值
- google-apps-script - 用户无权调用 showModalDialog()
- hive - 使用 sqoop 将数据从 CSV 导入 Avro 表的命令