private async Task ProcessInnerAsync(IGlobe globe, ISector sector, IActor actor, SectorTransition transition) { var sectorNode = transition.SectorNode; //TODO Разобраться с этим кодом. // https://blog.cdemi.io/async-waiting-inside-c-sharp-locks/ //Asynchronously wait to enter the Semaphore. If no-one has been granted access to the Semaphore, code execution will proceed, otherwise this thread waits here until the semaphore is released #pragma warning disable CA2007 // Consider calling ConfigureAwait on the awaited task await _semaphoreSlim.WaitAsync(); #pragma warning restore CA2007 // Consider calling ConfigureAwait on the awaited task try { if (sectorNode.State != SectorNodeState.SectorMaterialized) { await _globeExpander.ExpandAsync(sectorNode).ConfigureAwait(false); globe.AddSectorNode(sectorNode); } // It was used as fallback later. var oldActorNode = actor.Node; try { sector.ActorManager.Remove(actor); } catch (InvalidOperationException exception) { // Пока ничего не делаем Console.WriteLine(exception); Console.WriteLine(sector.GetHashCode()); Console.WriteLine(actor); } var nextSector = sectorNode.Sector; var transitionItem = new TransitionPoolItem(actor.Person, actor.TaskSource, nextSector, sector, oldActorNode); _transitionPool.Push(transitionItem); } finally { //When the task is ready, release the semaphore. It is vital to ALWAYS release the semaphore when we are ready, or else we will end up with a Semaphore that is forever locked. //This is why it is important to do the Release within a try...finally clause; program execution may crash or take a different path, this way you are guaranteed execution _semaphoreSlim.Release(); } }