我正在尝试在循环的异步电子邮件发件人中的每条消息之间添加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()),但看起来我正在使用解决方案,在这里不适用于我。有什么想法吗?
答案 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。
示例类似于
protected async void OnClick(object sender, EventArgs e)
{
await // rest of code here;
}