private async Task <ResGroupModel <TModel> > GetGroupAsync <TModel>(WorksheetEntry worksheet, SemaphoreSlim semaphore, IAggregateProgress progress, CancellationToken cancellationToken) where TModel : IRowModel, new() { uint rowsPerBatch = MaxReadBatchSize / worksheet.Cols; IEnumerable <uint> batchStartIndexes = Enumerable.Range(0, (int)(worksheet.Rows / rowsPerBatch + 1)).Select(batchIndex => (uint)(batchIndex * rowsPerBatch + 1)); var cellsQueries = batchStartIndexes.Select(rowIndex => { var cellsQuery = worksheet.GetCellsQuery(); cellsQuery.MinimumRow = rowIndex; cellsQuery.MaximumRow = rowIndex + rowsPerBatch; if (cellsQuery.MaximumRow > worksheet.Rows) { cellsQuery.MaximumRow = worksheet.Rows; } return(cellsQuery); }).ToList(); var progresses = progress.CreateParallelProgresses(cellsQueries.Select(cq => (double)cq.MaximumRow - cq.MinimumRow).ToList()); var cellsTasks = cellsQueries.Zip(progresses, async(cellsQuery, p) => { await semaphore.WaitAsync(cancellationToken); try { var cellsFeed = await Service.GetFeedAsync(cellsQuery, p, cancellationToken); return(cellsFeed.Entries.Cast <CellEntry>()); } finally { semaphore.Release(); } }); var cells = (await Task.WhenAll(cellsTasks)).SelectMany(cs => cs).ToList(); return(await ProcessGroupAsync <TModel>(worksheet, cells, cancellationToken)); }
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; } }