Velocidad de aceleración del proceso de envío de correo electrónico

Lo siento, el título es un poco malo, no pude decirlo correctamente.

Edit: debería tener en cuenta que esta es una aplicación de consola C #

He creado un prototipo de un sistema que funciona así (esto es un pseudocodificado aproximado):

var collection = grabfromdb();

foreach (item in collection) {
    SendAnEmail();
}

Enviar un correo electrónico

SmtpClient mailClient = new SmtpClient;
mailClient.SendCompleted += new SendCompletedEventHandler(SendComplete);
mailClient.SendAsync('the mail message');

SendComplete:

if (anyErrors) {
    errorHandling()
}
else {
    HitDBAndMarkAsSendOK();    
}

Obviamente esta configuración no es ideal. Si la colección inicial tiene, digamos 10,000 registros, entonces va a generar hasta 10,000 instancias de smtpclient en un tiempo bastante corto tan rápido como pueda pasar por las filas, y probablemente aspire en el proceso.

Mi juego final ideal es tener algo así como 10 correos electrónicos concurrentes saliendo a la vez.

Me viene a la mente una solución hacky: agregue un contador, que aumenta cuando se llama a SendAnEmail (), y disminuye cuando se envía SendComplete. Antes de llamar a SendAnEmail () en el bucle inicial, verifique el contador, si es demasiado alto, luego duerma por un período de tiempo pequeño y luego verifíquelo nuevamente.

No estoy seguro de que sea una gran idea, y creo que la mente SO colmena tendría una manera de hacerlo correctamente.

Tengo muy poco conocimiento de subprocesos y no estoy seguro de si sería un uso apropiado aquí. Por ejemplo, al enviar un correo electrónico en un subproceso en segundo plano, primero verifique el número de subprocesos secundarios para asegurarse de que no se usen demasiados. O si hay algún tipo de 'aceleración de subprocesos' incorporada.

Actualiza

Siguiendo los consejos de Steven A. Lowe, ahora tengo:

Un diccionario que contiene mis correos electrónicos y una clave única (este es el correo electrónico queUn método FillQue, que llena el diccionario Un método ProcessQue, que es un hilo de fondo. Comprueba la cola y SendAsycs cualquier correo electrónico en la cola. Un delegado de SendCompleted que elimina el correo electrónico de la cola. Y vuelve a llamar a FillQue.

Tengo algunos problemas con esta configuración. Creo que me he perdido el barco con el hilo de fondo, ¿debería generar uno de estos para cada elemento del diccionario? ¿Cómo puedo hacer que el hilo se "cuelgue" por falta de una palabra mejor, si el correo electrónico vacía el hilo termina?

actualización final

He puesto un 'while (verdadero) {}' en el hilo de fondo. Si la cola está vacía, espera unos segundos e intenta nuevamente. Si la cola está repetidamente vacía, 'rompo' el tiempo y el programa termina ... Funciona bien. Aunque estoy un poco preocupado por el negocio 'while (verdadero)' ...

Respuestas a la pregunta(5)

Su respuesta a la pregunta