Thread.Sleep и Task.Delay уничтожают основной поток в зацикленном процессе - PullRequest
0 голосов
/ 07 ноября 2018

Я пытаюсь добавить 10-секундную задержку между каждым сообщением в циклическом асинхронном отправителе электронной почты. Причина задержки заключается в ограничении количества электронных писем, отправляемых в течение определенного периода времени.

Это работает, но как только я добавляю 10-секундную задержку в цикл, используя либо Thread.Sleep, либо Task.Delay, основной поток просто сбрасывается, и отправляется только первое электронное письмо.

Вот мой код:

    Task t = Task.Run( async ( ) =>
    {
        foreach( var message in messages )
        {
            using( var client = new SmtpClient( ) )
            {
                await client.SendMailAsync( message );
                message.Dispose( );
            }
            // all of these seem to kill the main thread
            //System.Threading.Thread.Sleep( TimeSpan.FromSeconds( 10 ) );
            await Task.Delay( TimeSpan.FromSeconds( 10 ) );
            //await new Task( ( ) => Task.Delay( TimeSpan.FromSeconds( 10 ) ) );
        }
    } );

Я посмотрел на Разница между Task.Delay () и новой Task (() => Thread.Sleep ()) , но похоже, что я использую решение, которое не работает для меня здесь. Есть идеи?

1 Ответ

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

Вы не ожидаете первого задания, таким образом, оно становится заданием fire-and-Forgot . Если следующая строка, скажем, конец консольного приложения Main(), то программа завершит работу до завершения остальных задач! Удаление задержки увеличит вероятность того, что другие задачи будут выполнены вовремя.

Это веб-приложение ASP.NET.

В этом случае вы должны использовать async "полностью" , что означает, что вы не только должны иметь await здесь:

Task t = Task.Run( async ( ) => { ... }

... становится

await Task.Run( async ( ) => { ... }

... но также и все дерево вызовов вплоть до метода контроллера ASP.NET

public async Task SomeMethodOnMyController ()
{
    await SomethingAsync();
}

async Task SomethingAsync()
{
   // do something thrilling here

   await _emailSystem.SendEmailsAsync();

   // do something thrilling here
}

... где SendEmailsAsync - это, по сути, ваш код, указанный в вопросе.

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

РЕДАКТИРОВАТЬ: для веб-форм ASP.NET

Примером будет что-то вроде

protected async void OnClick(object sender, EventArgs e)
{
    await // rest of code here;
}

Расскажите подробнее

...