Thread.Sleep和Task.Delay在循环进程中杀死主线程

时间:2018-11-07 04:51:46

标签: c# asp.net multithreading asynchronous task

我正在尝试在循环的异步电子邮件发件人中的每条消息之间添加10秒的延迟。延迟的原因是限制在给定时间段内发送的电子邮件数量。

它可以工作,但是一旦我使用Thread.Sleep或Task.Delay将10秒的延迟添加到循环中,主线程似乎就掉线了,只发送了第一封电子邮件。

这是我的代码:

    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 ) ) );
        }
    } );

我看了Difference between Task.Delay() and new Task(()=>Thread.Sleep()),但看起来我正在使用解决方案,在这里不适用于我。有什么想法吗?

1 个答案:

答案 0 :(得分:1)

您没有在等待第一个任务,因此将其变成了“发射即忘”任务。如果下一行是控制台应用程序Main()的结尾,则该程序将在其余任务完成之前退出!消除延迟将增加其他任务及时完成的​​可能性。

  

这是一个ASP.NET Web应用程序。

在这种情况下,您应该使用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 WebForms

示例类似于

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

告诉我更多