TGStat
TGStat
Введите текст для поиска
Расширенный поиск каналов
  • flag Russian
    Язык сайта
    flag Russian flag English flag Uzbek
  • Вход на сайт
  • Каталог
    Каталог каналов и чатов Региональные подборки Тематические подборки Платные каналы Поиск каналов
    Добавить канал/чат
  • Рейтинги
    Рейтинг каналов Рейтинг чатов Рейтинг публикаций
    Рейтинги брендов и персон
  • Аналитика
  • Поиск по публикациям
  • Мониторинг Telegram
  • Продвижение
    Реклама через Яндекс Бизнес Реклама в каналах через TGStat Agency Реклама на сайте TGStat.ru
НеСерьезный шарпист

4 Oct 2024, 17:30

Открыть в Telegram Поделиться Пожаловаться

SynchronizationContext

Если упрощать и не вдаваться в точные определения SynchronizationContext в .NET позволяет передавать между потоками задачи (делегаты) на выполнение. В десктоп приложениях WinForms/WPF/UWP, например, все задачи, связанные с обновлением интерфейса, должны выполняться в основном Main потоке. Когда приложение запускается, оно автоматически создает контекст синхронизации для этого потока. Если выполнение кода уходит в фоновый поток, SynchronizationContext позволяет вернуться обратно к основному UI-потоку. При обращении к UI из другого фонового потока получим исключение.
private void SomeWork()
{
SynchronizationContext context = SynchronizationContext.Current;

Task.Run(() =>
{
Thread.Sleep(1000);

// Передача задачи на UI поток
context.Post(() =>
{
StatusLabel.Content = "Done!";
},
null);
});
}

При асинхронном выполнении, когда мы ставим задачу на ожидание await, среда выполнения автоматически сохраняет текущий SynchronizationContext и после завершения асинхронной операции возвращает выполнение в этот контекст. Таким образом, не нужно вручную управлять потоками, контекст синхронизации делает это за нас.
private async void Button_Click(object sender, RoutedEventArgs e)
{
await Task.Run(() =>
{
Thread.Sleep(1000);
});

// После await будет продолжено выполнение в UI потоке
StatusLabel.Content = "Done!";
}

Зачастую бывает не обязательно возвращаться в исходный поток после асинхронной операции. В таких случаях можно отключить использование контекста с помощью метода ConfigureAwait(false) и позволить продолжить выполнение кода, после завершения асинхронной операции, в любом доступном потоке.
await WorkAsync().ConfigureAwait(false);

А чтобы каждый раз не прописывать ConfigureAwait(false), можно переключиться на пул потоков с помощью AsyncHelper.RedirectToThreadPool().

А теперь поговорим про ASP.NET)))
В ASP.NET Core НЕТ SynchronizationContext.

Проблема такого подхода для веб приложения довольно очевидна. HTTP-запрос в старой версии ASP.NET обрабатывался в рамках отдельного потока из пула потоков. После того как поток назначался для обработки запроса, он оставался связан с запросом до тех пор, пока обработка не завершалась, за что отвечал контекст синхронизации SynchronizationContext, гарантировавший продолжение выполнения кода в рамках запроса на одном и том же потоке.

По окончанию асинхронной операции, продолжение кода асинхронного метода ставилось в очередь на продолжение выполнения в данном потоке, после чего происходит ожидание выполнения всех других "продолжений". Когда оно готово к запуску, поток берется из пула потоков, входит в контекст запроса, а затем возобновляет выполнение обработчика. Таким образом, имеем проблему с производительностью и масштабируемостью из-за потребности в большом количестве потоков в пуле.

При использовании подхода ASP.NET Core без контекста каждый запрос может быть обработан любым доступным потоком, а при асинхронной операции, когда асинхронный обработчик возобновляет выполнение, берется любой свободный поток из пула и выполняет продолжение. Очередь контекста избегается, и нет необходимости «входить» в контекст запроса. Соответственно, сейчас отпадает потребность писать ConfigureAwait(false), т.к. это нам по факту ничего не даст))

Еще забавляет, когда интервьюеры на собесах на позицию ASP.NET разработчика спрашивают про ConfigureAwait(false), ожидая ответа про отвязку от контекста и выполнение в любом потоке пулла, когда их проект на .NET 8))) В сентябре был на 10+ технических собесах и данный вопрос был в процентах 40 случаев. Хотя чего я хочу, когда CTO одной галеры пытался доказывать мне, что Dictionary - НЕ хештейбл 🤡

P.S. Да, мое месячное отсутствие связано с прохождением кучи собесов. Получил 5 офферов, выбрал классный проект, но не смогу перейти сейчас из-за возможных проблем с военкоматом при смене компании 💧

3.8k 0 46 8 29
Каталог
Каталог каналов и чатов Подборки каналов Поиск каналов Добавить канал/чат
Рейтинги
Рейтинг каналов Telegram Рейтинг чатов Telegram Рейтинг публикаций Рейтинги брендов и персон
API
API статистики API поиска публикаций API Callback
Наши каналы
@TGStat @TGStat_Chat @telepulse @TGStatAPI
Почитать
Академия TGStat Исследование Telegram 2019 Исследование Telegram 2021 Исследование Telegram 2023
Контакты
Справочный центр Поддержка Почта Вакансии
Всякая всячина
Пользовательское соглашение Политика конфиденциальности Публичная оферта
Наши боты
@TGStat_Bot @SearcheeBot @TGAlertsBot @tg_analytics_bot @TGStatChatBot