Exemple #1
0
        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();
            }
        }
        private async Task ProcessInternalAsync(IGlobe globe, ISector sourceSector, IActor actor,
                                                SectorTransition transition)
        {
            var sectorNode = transition.SectorNode;

            await _semaphoreSlim.WaitAsync().ConfigureAwait(false);

            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;

                sourceSector.ActorManager.Remove(actor);

                var targetSector = sectorNode.Sector;

                if (targetSector is null)
                {
                    throw new InvalidOperationException();
                }

                var transitionItem = new TransitionPoolItem(
                    actor.Person,
                    actor.TaskSource,
                    targetSector,
                    sourceSector,
                    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();
            }
        }