Должен ли семафорлис быть в контроллере, а не дальше в цепочке? - PullRequest
0 голосов
/ 24 ноября 2018

В нашей производственной среде мы наблюдаем тупиковое поведение, и мне интересно, правильно ли мы используем семафорлис.

В нашем репозитории код выглядит следующим образом:

public async Task<IActionResult> CreateAsync([FromBody] SomeModel someModel)
{
    var result = await _someClass.CreateArende(someModel);

    return result;
}

public async Task<IActionResult> RegisterAsync([FromBody] SomeModel someModel)
{
    var result = await _someClass.RegisterArende(someModel);

    return result;
}

Нет семфорслима вУровень контроллера нашего API, но в некотором классе выглядит следующим образом:

public class SomeClass {

    protected static SemaphoreSlim _semphoreSlimCreateArende = new SemaphoreSlim(1, 1);

    public async virtual Task<SomeResponseDto> CreateArende(SomeModel someModel)
    {
        try
        {
            await _semphoreSlimCreateArende.WaitAsync();

        }
        finally
        {
            try
            {
                _semphoreSlimCreateArende.Release();
            }
            catch (Exception)
            {
            }
        }

        return new SomeResponseDto()
        {
            ...
        };
    }

    public async virtual Task<SomeResponseDto> RegisterArende(SomeModel someModel)
    {
        try
        {
            await _semphoreSlimCreateArende.WaitAsync();

        }
        finally
        {
            try
            {
                _semphoreSlimCreateArende.Release();
            }
            catch (Exception)
            {
            }
        }

        return new SomeResponseDto()
        {
            ...
        };
    }

}

Должен ли семафорлис быть на уровне контроллера?Или я должен изменить действия контроллеров, чтобы они не были асинхронными?

1 Ответ

0 голосов
/ 24 ноября 2018

Этот вопрос немного разрознен, однако давайте попытаемся разобраться в нем немного

Во-первых, Давайте разберемся в правильном шаблоне

try
{
    await _semphoreSlimCreateArende.WaitAsync();

    // do your sync work here

}
finally
{
    // if this throws you are certainly doing something wrong
    _semphoreSlimCreateArende.Release(); 
}

Во-вторых, , вам следует отобрать у вас клавиатуру для этого

catch (Exception)
{
}

Никогда не ешьте вслепую исключения, а если вы получаете их на _semphoreSlimCreateArende.Release, у вас уже есть серьезные проблемы, и вынужно выяснить, почему

Должны ли семафорлимы быть на уровне контроллера?

Использовать их на уровне, который имеет больше смысла, я имею в виду, если вам нужносинхронизировать кусок кода, синхронизировать его там, а не на 13 уровней.

Или я должен изменить действия контроллеров, чтобы они не были асинхронными?

, если у вас есть asnycработаем, сделаем ваш контроллер async и позволим ему распространяться вниз по стеку к вашему async коду

Мы имеем тупиковое поведение в нашей производственной среде, и мне интересно, правильно ли мы используем семафорлис.

Вау, мы такиеlking DataBase Deadlocks или Context Deadlocks.В любом случае все это звучит немного подозрительно

К вашему сведению

Использование SemaphoreSlim в веб-сервисе может быть неприятным подходом.SemaphoreSlim работает на спин-блокировке и не должен использоваться для чего-либо, что блокирует в течение любого периода времени.Спинлоки блокируют процессор, ожидая снятия блокировки.Идеально, если вы используете их, когда немного кусает блокировку, и в ситуациях, которые не блокируют дальше по цепочке.

Если вы используете код взаимоблокировки, то вам нужно точно определить, что вызывает тупик, если это взаимоблокировка на основе задач, то SemaphoreSlim не является подходящим инструментом для работы, если он неблокирующая гонка, тогда, возможно, это немного более приемлемо.Если это тупик базы данных, то у вас есть большая проблема.

...