c# - 长 API 调用 - 异步调用答案?
问题描述
我正在调用一个很慢的外部 API。目前,如果我暂时没有调用 API 来获取一些订单,则可以将调用分解为页面(分页)。
因此,获取订单可能会进行多次调用,而不是 1 次调用。有时每次通话可能需要大约 10 秒,因此总共可能需要大约一分钟,这太长了。
GetOrdersCall getOrders = new GetOrdersCall();
getOrders.DetailLevelList.Add(DetailLevelCodeType.ReturnSummary);
getOrders.CreateTimeFrom = lastOrderDate;
getOrders.CreateTimeTo = DateTime.Now;
PaginationType paging = new PaginationType();
paging.EntriesPerPage = 20;
paging.PageNumber = 1;
getOrders.Pagination = paging;
getOrders.Execute();
var response = getOrders.ApiResponse;
OrderTypeCollection orders = new OrderTypeCollection();
while (response != null && response.OrderArray.Count > 0)
{
eBayConverter.ConvertOrders(response.OrderArray, 1);
if (response.HasMoreOrders)
{
getOrders.Pagination.PageNumber++;
getOrders.Execute();
response = getOrders.ApiResponse;
orders.AddRange(response.OrderArray);
}
}
这是我上面代码的摘要...... getOrders.Execute() 是api触发的时候。
在第一个“getOrders.Execute()”之后有一个分页结果,它告诉我有多少页数据。我的想法是我应该能够为每个页面启动异步调用并填充 OrderTypeCollection。当所有调用都完成并且集合完全加载时,我将提交到数据库。
我以前从未通过 c# 进行过异步调用,我可以遵循 Async await 但我认为我的场景超出了我迄今为止所做的阅读范围?
问题:
- 我想我可以将它设置为异步触发多个调用,但我不确定如何检查所有任务何时完成,即准备好提交到数据库。
- 我在某处读过我想避免将 API 调用和 db 写入结合起来以避免锁定 SQL Server - 这是正确的吗?
如果有人能指出我正确的方向 - 将不胜感激。
解决方案
我想我可以将它设置为异步触发多个调用,但我不确定如何检查所有任务何时完成,即准备好提交到数据库。
是的,你可以打破这个
问题是ebay没有async Task Execute
方法,所以你只剩下阻塞线程调用并且没有IO 优化的异步等待模式。如果有的话,你可以利用一个TPL Dataflow管道,它是有async
意识的(并且全家人都可以玩),无论如何你都可以,尽管我提出了一个普通的TPL解决方案......
然而,一切都没有失去,只是回落到Parallel.For
和一个ConcurrentBag<OrderType>
例子
var concurrentBag = new ConcurrentBag<OrderType>();
// make first call
// add results to concurrentBag
// pass the pageCount to the for
int pagesize = ...;
Parallel.For(1, pagesize,
page =>
{
// Set up
// add page
// make Call
foreach(var order in getOrders.ApiResponse)
concurrentBag.Add(order);
});
// all orders have been downloaded
// save to db
注意:MaxDegreeOfParallelism
您可以配置它,也许将其设置为 50,尽管您给它多少并不重要,任务计划程序不会积极地给您线程,最初可能是 10 左右,并且增长缓慢。
您可以这样做的另一种方法是创建自己的Task Scheduler,或者只是使用老式Thread
Class启动您自己的 Threads
我在某处读过我想避免将 API 调用和 db 写入结合起来以避免锁定 SQL Server - 这是正确的吗?
- 如果您的意思是在慢速数据库插入中锁定,请使用 Sql Bulk Insert 和更新工具。
- 如果您的意思是像 DB 死锁错误消息中那样锁定,那么这是完全不同的事情,值得提出自己的问题
其他资源
For(Int32, Int32, ParallelOptions, 动作)
执行 for(在 Visual Basic 中为 For)循环,其中可以并行运行迭代并且可以配置循环选项。
存储配置 Parallel 类上方法操作的选项。
MaxDegreeOfParallelism
获取或设置此 ParallelOptions 实例启用的最大并发任务数。
表示一个线程安全的、无序的对象集合。
推荐阅读
- php - 来自 homebrew 的 php@7.0 的 PHP 扩展 mosquitto 安装
- wordpress - WordPress 导出/翻译/导入单页
- html-agility-pack - 从 URL 加载 html 的两种方法?
- jquery - 如何在 Laravel 中将数组从 Controller 发送到 JavaScript?
- facebook - Facebook App 域与 localhost 一起使用,但不适用于我的网站
- xpath - 替换xpath中的完整字符串刚刚得到
- amazon-web-services - Fargate 上的 AWS docker - 是否可以选择不同的内核?
- google-apps-script - 有没有办法在 Google Drive 上为 Google Web App 托管一个网站图标?
- perl - Perl:复杂数据结构的校验和
- vba - 努力从 VLOOKUP 创建一个带有 MIN 的函数