private async Task PushCellsAsync <TModel>(WorksheetEntry worksheet, ResGroupModel <TModel> group, SemaphoreSlim semaphore, IAggregateProgress progress, CancellationToken cancellationToken) where TModel : IRowModel { var progresses = progress.CreateParallelProgresses(0.2, 0.8); var mappingProgress = progresses[0]; var updatingProgress = progresses[1]; var cellFeed = await Service.GetFeedAsync(worksheet.GetCellsQuery(), cancellationToken : cancellationToken); string cellsFeedUrl = cellFeed.Self; string batchUrl = cellFeed.Batch; var resCells = await CreateSheetCellInfos(group, cancellationToken); var cellGroups = Devide(resCells, MaxBatchSize); var mappingTasks = (await MapFeedBatchesAsync(cellGroups, cellsFeedUrl, batchUrl, mappingProgress, cancellationToken)) .Select(async kvp => { var mappingFeed = kvp.Key; var p = kvp.Value; await semaphore.WaitAsync(cancellationToken); try { return(await Service.BatchFeedAsync(mappingFeed, TimeOutAttemptsCount, p, cancellationToken)); } finally { semaphore.Release(); } }); //Mapping cells. List <CellFeed> mappingFeeds = new List <CellFeed>(cellGroups.Count); foreach (var mappingTask in mappingTasks) { mappingFeeds.Add(await mappingTask); } //Updating cells. var updatingTasks = (await UpdateFeedBatchesAsync(cellGroups, mappingFeeds, cellsFeedUrl, batchUrl, updatingProgress, cancellationToken)) .Select(async kvp => { var updateFeed = kvp.Key; var p = kvp.Value; await semaphore.WaitAsync(cancellationToken); try { return(await Service.BatchFeedAsync(updateFeed, TimeOutAttemptsCount, p, cancellationToken)); } finally { semaphore.Release(); } }); foreach (var updatingTask in updatingTasks) { await updatingTask; } }