Reputation: 371
I'm attempting to add a 10 second delay between each message in a looped asynchronous email sender. The reason for the delay is to limit the number of emails being sent within a given time period.
It works, but as soon as I add the 10 second delay to the loop using either Thread.Sleep or Task.Delay, the main thread just seems to drop so that only the first email is sent.
Here is my code:
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 ) ) );
}
} );
I looked at Difference between Task.Delay() and new Task(()=>Thread.Sleep()), but the it looks like I am using the solution, which doesn't work for me here. Any ideas?
Upvotes: 0
Views: 1137
Reputation:
You are not awaiting the first task thus making it a fire-and-forget task. If the next line is say the end of a console app's Main()
, then the program is going to exit before the rest of the tasks complete! Removing the delay is going to increase the probability that the other tasks complete in time.
It's a ASP.NET web application.
In that case you should be using async
"all the way" which means that not only should you have an await
here:
Task t = Task.Run( async ( ) => { ... }
...becoming
await Task.Run( async ( ) => { ... }
...but also your whole call tree all the way back out to your ASP.NET controller method
public async Task SomeMethodOnMyController ()
{
await SomethingAsync();
}
async Task SomethingAsync()
{
// do something thrilling here
await _emailSystem.SendEmailsAsync();
// do something thrilling here
}
...where SendEmailsAsync
is essentially your code provided in the question.
If you don't do this, then there is the chance ASP.NET will be unaware that the method is performing async operations and could prematurely recycle your AppDomain before your email processing is complete.
The example would be something like
protected async void OnClick(object sender, EventArgs e)
{
await // rest of code here;
}
Upvotes: 1