长API调用-异步调用答案吗?

时间:2018-10-30 03:58:04

标签: c# async-await

我正在调用一个缓慢的外部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);
            }
        }

这是我上面的代码的摘要... API触发时,getOrders.Execute()是

在第一个“ getOrders.Execute()”之后,有一个分页结果,告诉我有多少页数据。我的想法是,我应该能够为每个页面启动一个异步调用并填充OrderTypeCollection。当所有调用都完成并且集合已完全加载时,我将提交数据库。

我以前从未通过c#进行过异步调用,可以有点等待Async的等待,但是我认为我的情况超出了我到目前为止的阅读范围?

问题:

  1. 我认为我可以将其设置为异步触发多个调用,但是我不确定如何检查所有任务何时完成(即准备提交给db)。
  2. 我读过一些地方,希望避免将API调用和db write结合使用,以避免锁定SQL Server-这是正确的吗?

如果有人可以将我指向正确的方向,将不胜感激。

2 个答案:

答案 0 :(得分:3)

  

我想我可以将其设置为异步触发多个呼叫   但我不确定如何检查所有任务的完成时间,即   准备提交到数据库。

是的,您可以分手

问题是 ebay 没有async Task Execute方法,因此您只能阻止线程调用,并且没有 IO优化的异步等待模式。如果有的话,您可以利用{em {1}}知道的 TPL Dataflow 管道(并且让整个家庭玩得开心),尽管我建议使用香草 TPL 解决方案...

但是,一切并没有丢失,只是回到asyncParallel.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 ,也许将其设置为50,尽管您给它多少钱并不重要,任务计划程序不会主动为您提供线程,最初可能只有10个左右,并且增长缓慢。

另一种方法是创建自己的 Task Scheduler ,或者只是使用老式的MaxDegreeOfParallelism

启动自己的线程
  

我读过一些地方,希望避免将API调用与   数据库写入以避免锁定在SQL Server中-这是正确的吗?

  • 如果要像在慢速数据库插入中那样锁定,请使用Sql Bulk Insert和更新工具。
  • 如果您要像在DB死锁错误消息中那样进行锁定,那么这是完全不同的事情,值得提出自己的问题

其他资源

For(Int32, Int32, ParallelOptions, Action)

  

执行for(在Visual Basic中为For)循环,在该循环中可以运行迭代   可以并行和循环配置选项。

ParallelOptions Class

  

存储用于在Parallel上配置方法操作的选项   课。

     

MaxDegreeOfParallelism

     

获取或设置由此启用的最大并发任务数   ParallelOptions实例。

ConcurrentBag Class

  

表示线程安全的无序对象集合。

答案 1 :(得分:0)

ConcurrentBag<T>类可用于满足您的一个问题:“我认为我可以将其设置为异步触发多个调用,但是我不确定如何检查何时所有任务都已完成,即准备提交给数据库。”

该通用类可用于运行您的每个任务,并等待所有任务完成以进行进一步处理。它是线程安全的,对于并行处理很有用。