public static async Task <TResult[]> ParallelForEachAsync <T, TResult>(this IEnumerable <T> source, Func <T, Task <TResult> > action, int degreeOfParallelism, CancellationToken cancellationToken = default) { degreeOfParallelism = Math.Min(degreeOfParallelism, source.Count()); using (var enumerator = new ConcurrentEnumerator <T>(source)) { var tasks = Enumerable.Range(0, degreeOfParallelism) .Select(async x => { var list = new List <TResult>(); for (var item = enumerator.GetNext(); item.HasValue; item = enumerator.GetNext()) { if (cancellationToken.IsCancellationRequested) { return(list); } var value = await action(item.Value); list.Add(value); } return(list); }); var results = await Task.WhenAll(tasks); cancellationToken.ThrowIfCancellationRequested(); return(results.SelectMany(x => x).ToArray()); } }
public void RebuildDirtyCells(RenderFlags renderFlags) { using (MyUtils.ReuseCollection <MyCubeGridRenderCell>(ref m_dirtyCellsBuffer)) { using (ConcurrentEnumerator <SpinLockRef.Token, MyCubeGridRenderCell, HashSet <MyCubeGridRenderCell> .Enumerator> enumerator = this.m_dirtyCells.GetEnumerator()) { while (true) { if (!enumerator.MoveNext()) { this.m_dirtyCells.Clear(); break; } m_dirtyCellsBuffer.Add(enumerator.Current); } } object cellsUpdateLock = this.m_cellsUpdateLock; lock (cellsUpdateLock) { using (List <MyCubeGridRenderCell> .Enumerator enumerator2 = m_dirtyCellsBuffer.GetEnumerator()) { while (enumerator2.MoveNext()) { enumerator2.Current.RebuildInstanceParts(renderFlags); } } } } }