Nope, this code doesn't respect the semaphore. It just send all emails without concurrency degree limiting by semaphore. Because return SendEmailAsync
returns right after Task
object is received not the method finished, then semaphore is released immediately. Thus semaphore thottles only requests creation which I assume is fast.
The fix is await
in try
clause.
public async Task SendEmailAsync(string subject, string htmlMessage,
IEnumerable<string> recipients, string? attachment)
{
using SemaphoreSlim semaphore = new(10);
await Task.WhenAll(recipients.Select(recipient =>
SendEmailAsync(subject, htmlMessage, recipient, attachment, semaphore)));
}
private async Task SendEmailAsync(string subject, string htmlMessage,
string recipient, string? attachment, SemaphoreSlim semaphore)
{
await semaphore.WaitAsync();
try
{
await SendEmailAsync(subject, htmlMessage, recipient, attachment);
}
finally
{
semaphore.Release();
}
}
The rest part of the code looks fine for me. Probably I can only suggest to use OOP to encapsulate data for bulk emailing into some class. It would make furure code improvements easier.