繁体   English   中英

异步循环调用的异步方法的任何好处

[英]Any benefit to an Async method that Synchronously Loops a call

我正在编写一个必须通过SDK从外部api提取数据的程序。 我不太熟悉await / async操作-但是知道每个调用的SDK提供了Async方法。 GetResultsAsync<TObject>()

每个查询都有返回记录的限制-因此,为了获取该月的所有记录-我必须按ID排序,然后循环。 这是当前“同步”调用的一些示例代码。 只要我得到结果-我就会检查更多。

public List<TimeEntry> ListTimeEntries(DateTime startDate, DateTime endDate)
{
    var page = 1;
    var hasMore = false;
    var qry = string.Format("timeStart >= [{0}] and timeEnd <= [{1}]", startDate, endDate); //For example
    var results = List<TimeEntry>();
    do
    {
        var newItems = api.GetEntries(qry, "id desc", maxPageSize, page).GetResults<List<TimeEntry>>();
        results.AddRange(newItems);
        hasMore = newItems.Any();
        page++;
    } while (hasMore);
    return results;
}

这可能要说4-5个循环(或更多取决于日期),但显然很耗时。

如果我将其简单地转换为async方法-是否可以同时进行其他同步调用? 假设我还需要在同一时间段获取服务凭单和项目凭单-但在返回所有凭单之前,不执行任何逻辑处理。 我可以让所有三个呼叫异步运行吗?

这是目标

var startDate = DateTime.Now.AddDays(-30);
var endDate = DateTime.Now;

var timeTask = ListTimeEntries(startDate, endDate);
var serviceTask = ListServiceTickets(startDate, endDate);
var projectTask = ListProjectTickets(startdDate, endDate);

var timeEntries = await timeTask;
var serviceTickets = await serviceTask;
var projectTickets = await projectTask;

// Do what ever processing logic I need now.

如何实现?

例如#1-会使方法作为async工作吗? 例如:

public async Task<List<TimeEntry>> ListTimeEntries(DateTime startDate, DateTime endDate)
{
    var page = 1;
    var hasMore = false;
    var qry = string.Format("timeStart >= [{0}] and timeEnd <= [{1}]", startDate, endDate); //For example
    var results = List<TimeEntry>();
    do
    {
        var newItems = api.GetEntries(qry, "id desc", maxPageSize, page).GetResults<List<TimeEntry>>();
        results.AddRange(newItems);
        hasMore = newItems.Any();
        page++;
    } while (hasMore);
    return results;
}

或实际上使用SDK的GetResultsAsync<>方法(例如示例2)是否会有任何好处:

public async Task<List<TimeEntry>> ListTimeEntries(DateTime startDate, DateTime endDate)
{
    var page = 1;
    var hasMore = false;
    var qry = string.Format("timeStart >= [{0}] and timeEnd <= [{1}]", startDate, endDate); //For example
    var results = List<TimeEntry>();
    do
    {
        var newItemsTask = api.GetEntries(qry, "id desc", maxPageSize, page).GetResultsAsync<List<TimeEntry>>();
        var newItems = await newItemsTask;
        results.AddRange(newItems);
        hasMore = newItems.Any();
        page++;
    } while (hasMore);
    return results;
}

虽然我知道这些方法在内部仍在同步运行-我希望每次对ListTimeEntriesListServiceTicketsListProjectTickets调用都异步发生以加快速度。

我想/由于缺乏知识,我的想法/希望是每个同步调用将使用不同的线程,从而加快了整个过程。 我离基地远吗?

我会做类似以下的事情。 您将需要了解有关API限制的潜在问题,并且当然有可能在所有4个线程完成之前至少有3个额外的请求正在进行中-如果要检索的页面很多,则要付出很小的代价。

public async Task<IList<TimeEntry>> CallSomething(DateTime startDate, DateTime endDate)
{
    var qry = string.Format("timeStart >= [{0}] and timeEnd <= [{1}]", startDate, endDate); //For example

    const threadCount = 4;

    var isComplete = new ManualResetEvent();
    var page = 0;
    var results = new ConcurrentBag<TimeEntry>();
    var thread = new Task[threadCount];
    for(var i = 0; i < threadCount; ++i)
    {
        thread[i] = Task.Run(
            async () =>
            {
                while(!isComplete.WaitOne(TimeSpan.Zero))
                {
                    var localPage = Interlocked.Increment(ref page);

                    var newItems = await api
                        .GetEntries(qry, "id desc", maxPageSize, localPage)
                        .GetResultsAsync<List<TimeEntry>>()
                        .ConfigureAwait(false);

                    if (!newItems.Any())
                    {
                        isComplete.Set();
                    }
                    else
                    {
                        foreach (var item in newItems)
                        {
                            results.Add(item);
                        }
                    }
                }
            })
        )
    }

    await Task.WhenAll(thread).ConfigureAwait(false);

    return results.OrderByDescending(f => f.Id).ToList();
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM