I am using the C# client library for SendGrid version 9.27.0.
The only way I can get it to send an email is by adding Wait() to end of my method.
I understand the await operator is a promise to return back to the point in code after the asynchronous method is finished.
But why do I need to add Wait()? Isn't that converting the asynchronous method to synchronous? If so, what's the point in making it async?
Program.cs
static void Main(string[] args) {
//var customerImport = new CustomerImport();
//customerImport.DoImport();
var mailClient = new MailClient();
var recipients = new List<string>();
recipients.Add("[email protected]");
//Never sends an email
var response = mailClient.SendMail("[email protected]", recipients, "Test email", "This is a test of the new SG client", false);
//Will send an email
mailClient.SendMail("[email protected]", recipients, "Test email", "This is a test of the new SG client", false).Wait();
}
MailClient.cs
public async Task SendMail(string emailFrom, List<string> emailTo, string subject, string body, bool isPlainText) {
try {
var apiKey = Utils.GetConfigValue("sendgridAPIKey");
var emails = new List<EmailAddress>();
foreach (string email in emailTo) {
emails.Add(new EmailAddress(email));
}
var plainTextContent = "";
var htmlContent = "";
if (!isPlainText) {
htmlContent = body;
} else {
plainTextContent = body;
}
var message = MailHelper.CreateSingleEmailToMultipleRecipients(new EmailAddress(emailFrom, "LobbyCentral"), emails, subject, plainTextContent, htmlContent);
//if (metaData != null)
// message.AddCustomArgs(metaData);
foreach (string filename in FileAttachments) {
if (System.IO.File.Exists(filename)) {
using (var filestream = System.IO.File.OpenRead(filename)) {
await message.AddAttachmentAsync(filename, filestream);
}
}
}
foreach (PlainTextAttachmentM plainTextM in PlainTextAttachments) {
byte[] byteData = Encoding.ASCII.GetBytes(plainTextM.Content);
var attachment = new Attachment();
attachment.Content = Convert.ToBase64String(byteData);
attachment.Filename = plainTextM.AttachmentFilename;
attachment.Type = "txt/plain";
attachment.Disposition = "attachment";
message.AddAttachment(attachment);
}
var client = new SendGridClient(apiKey);
var response = await client.SendEmailAsync(message);
if (response.IsSuccessStatusCode) {
if (DeleteAttachmentsAfterSend && FileAttachments.Count > 0) {
foreach (string filename in FileAttachments) {
if (System.IO.File.Exists(filename)) {
System.IO.File.Delete(filename);
}
}
}
} else {
Utils.DebugPrint("error sending email");
}
} catch (Exception ex) {
throw new Exception(string.Format("{0}.{1}: {2} {3}", System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.FullName, System.Reflection.MethodBase.GetCurrentMethod().Name, ex.Message, ex.StackTrace));
}
}
Calling mailClient.SendMail starts a Task, but doesn't wait for its completion.
If that's the last instruction of you program, the program simply ends before the tasks can finish.
You want your last instructions to start and wait for the task's completion. You can do that by using either of the following.
Make your Main async. (That's what I would personally do.)
// Signature changed to async Task instead of void.
static async Task Main(string[] args) {
// (...)
// Added await. Removed Wait.
await mailClient.SendMail("[email protected]", recipients, "Test email", "This is a test of the new SG client", false);
}
Use Wait like you're doing.
static void Main(string[] args) {
// (...)
var task = mailClient.SendMail("[email protected]", recipients, "Test email", "This is a test of the new SG client", false);
task.Wait();
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With