I need to send out a batch of reminder emails, never more than 100 emails per batch, using authenticated SMTP. This is happening on a WindowsService (no GUI).
The SMTP library we’re using raises a Sent event. In the Sent eventlistener, we grab some info from the Sent event’s args
and write some data to a SqlServer database via SqlClient library, to note the fact that the particular email has been sent to the recipient, and when it went out.
Is there any concern or issue for the Sent eventlistener when the emails are being sent out on multiple threads managed by ThreadPool?
pseudocode:
for each record in batch
{
var email = buildEmail(record);
ThreadPool.QueueUserWorkItem( a =>
{
if (!SmtpClient.Connected) SmtpClient.Connect();
if (!SmtpClient.Authenticated) SmtpClient.Authenticate();
if (SmtpClient.Authenticated) SmtpClient.Send(email);
});
}
SmtpClient.Sent += (sender, args) =>
{
//get info from args
// populate SqlCommand parameters
ThreadPool.QueueUserWorkItem(b =>
{
UpdateDatabase(info);
});
};
4
From the code it looks like it should work. Spinning off queued threads to the thread pool from an event listener should not cause issues (and I use a similar pattern is some of my code).
You will want to stress test the code to make sure that through put is enough to keep up and I would read up on error handling in multi threaded code (https://stackoverflow.com/questions/5218080/c-sharp-threadpool-queueuserworkitem-exception-handling for example).
Another pain point you will want to look out for is Connection Pool exhaustion. When you queue up your background threads if you have enough cpu capacity (or code UpdateDatabase using async
to release the thread while waiting) you can try to open more connections to the database than there are in the connection pool. When I was writing code very similar to yours I ran into issues with this and had to batch the actual updates to the database.
0