#c# #asynchronous #async-await
#c# #асинхронный #асинхронный-ожидание
Вопрос:
У меня есть BackgroundService/IHostedService
в ASP.NET Основное приложение API с a Channel
, которое ожидает, когда что-то еще будет записано на канале, чтобы оно могло прочитать его и обработать. Интервал, с которым элементы записываются в канал, может составлять каждые несколько секунд или минут.
Этот сервис долговечен (тот же срок службы, что и приложение API), а следовательно, и канал.
// Simplified/Example code
using System.Threading.Channels;
// ...
Channel<object> channel = Channel.CreateUnbounded<object>();
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
while (await channel.Reader.WaitToReadAsync(stoppingToken))
{
while (channel.Reader.TryRead(out string item))
{
// Process item
}
}
}
Мои вопросы таковы:
- Рекомендуется ли ждать
channel.Reader.WaitToReadAsync()
в течение длительного времени? (может пройти несколько минут, прежде чем элемент будет записан на канал) - Связан
channel.Reader.WaitToReadAsync()
ли ввод-вывод? (Освобождает ли это поток при использованииawait
?) - Лучше ли иметь
AutoResetEvent
и блокировать поток вместо использованияawait/async
? (Никаких потраченных впустую циклов процессора, так как поток просто перейдет в спящий режим)
Моя главная проблема заключается в том, что channel.Reader.WaitToReadAsync()
привязка к процессору и ожидание его в течение длительных периодов времени тратят ресурсы процессора, и лучше использовать другие методы, такие как AutoResetEvent
Ответ №1:
Все в порядке, ваши опасения необоснованны.
WaitToReadAsync
реализация исходит из UnboundedChannelReader
экземпляра Unbounded channel, который реализует специальный ожидающий, который сигнализируется, когда автор пишет.
Кроме того, поскольку это, по сути, только ожидание, поток используется повторно и создается продолжение до тех пор, пока не будет подан сигнал ожидающему.
Реализация каналов настолько оптимизирована и лаконична, насколько это возможно. Это не значит, что вы не можете свернуть самостоятельно, используя любые другие примитивы синхронизации, которые вам нравятся. Но шансы на то, что вы получите реализацию, такую же потоковую, легкую, повторно используемую, кэшированную и мощную, как каналы, будут невелики.
Короче говоря, потоки возвращаются в пул потоков, и никакая экстраординарная блокировка вращения или опрос не выполняются.