private async void ProcessNewChangedArgs() { try { using (_stateHelper.GetFuncWrapper()) { var lockSemCalledWrapper = _lockSem.GetCalledWrapper(); lockSemCalledWrapper.Called = true; using (await _lockSem.GetDisposable(true).ConfigureAwait(false)) { while (!_cts.IsCancellationRequested && lockSemCalledWrapper.Called) { lockSemCalledWrapper.Called = false; var currentChangesNumInDictToRemove = _changedArgsDict.Keys.Where(_ => _ <= _prevChangesCounter).ToList(); foreach (long key in currentChangesNumInDictToRemove) { MyNotifyCollectionChangedArgs <TItem> removedArgs; _changedArgsDict.TryRemove(key, out removedArgs); } MyNotifyCollectionChangedArgs <TItem> nextArgs; if ( _changedArgsDict.TryRemove( _prevChangesCounter + 1, out nextArgs ) ) { lockSemCalledWrapper.Called = true; if (nextArgs.ChangedAction == EMyCollectionChangedAction.Reset) { await ResetActionAsync().ConfigureAwait(false); } else if (nextArgs.ChangedAction == EMyCollectionChangedAction.NewItemsRangeInserted) { var insertIndex = nextArgs.NewItemsIndices[0]; var insertCount = nextArgs.NewItems.Count; if (insertCount > 0) { var insertArgs = new List <MutableTuple <int, TItem> >(); for (int i = 0; i < insertCount; i++) { insertArgs.Add( MutableTuple.Create( i + insertIndex, nextArgs.NewItems[i] ) ); } await _resultCollection.InsertRangeAtAsync( insertIndex, insertArgs ).ConfigureAwait(false); _originCollectionCopy.InsertRange( insertIndex, nextArgs.NewItems ); /**/ var currentResultCount = _originCollectionCopy.Count; var bulkUpdateArgs = new List <Tuple <int, MutableTuple <int, TItem> > >(); for (int i = insertIndex + insertCount; i < currentResultCount; i++) { bulkUpdateArgs.Add( Tuple.Create( i, MutableTuple.Create( i, _originCollectionCopy[i] ) ) ); } if (bulkUpdateArgs.Any()) { await _resultCollection.ReplaceBulkAsync( bulkUpdateArgs ).ConfigureAwait(false); } } _prevChangesCounter++; } else if (nextArgs.ChangedAction == EMyCollectionChangedAction.ItemsRangeRemoved) { var removeIndex = nextArgs.OldItemsIndices[0]; var removeCount = nextArgs.OldItems.Count; if (removeCount > 0) { await _resultCollection.RemoveRangeAsync( removeIndex, removeCount ).ConfigureAwait(false); _originCollectionCopy.RemoveRange( removeIndex, removeCount ); /**/ var currentResultCount = _originCollectionCopy.Count; var bulkUpdateArgs = new List <Tuple <int, MutableTuple <int, TItem> > >(); for (int i = removeIndex; i < currentResultCount; i++) { bulkUpdateArgs.Add( Tuple.Create( i, MutableTuple.Create( i, _originCollectionCopy[i] ) ) ); } if (bulkUpdateArgs.Any()) { await _resultCollection.ReplaceBulkAsync( bulkUpdateArgs ).ConfigureAwait(false); } } _prevChangesCounter++; } else if (nextArgs.ChangedAction == EMyCollectionChangedAction.ItemsChanged) { var count = nextArgs.NewItems.Count; var bulkUpdateArgs = new List <Tuple <int, MutableTuple <int, TItem> > >(); for (int i = 0; i < count; i++) { _originCollectionCopy[nextArgs.NewItemsIndices[i]] = nextArgs.NewItems[i]; bulkUpdateArgs.Add( Tuple.Create( nextArgs.NewItemsIndices[i], MutableTuple.Create( nextArgs.NewItemsIndices[i], nextArgs.NewItems[i] ) ) ); } if (bulkUpdateArgs.Any()) { await _resultCollection.ReplaceBulkAsync( bulkUpdateArgs ).ConfigureAwait(false); } _prevChangesCounter++; } else { throw new NotImplementedException(); } } } } } } catch (OperationCanceledException) { } catch (WrongDisposableObjectStateException) { } catch (Exception exc) { MiscFuncs.HandleUnexpectedError(exc, _log); } }