I read the documentation for async-await
feature, but still highly confused on how to structure async-await
code that calls SmtpClient.SendMailAsync()
method.
How should I rewrite the code to properly use async-await
?
Currently, my code looks like this:
Periodically PrivateSignal
is being called by the system to send out email notifications.
public override void PrivateSignal(IEventInformation ev)
{
TagEvent tag = (TagEvent)ev;
Task.Run(async () =>
{
try
{
await smptClient.SendMailAsync(CaptureRC.SmptFromEmailAddr,
ToEmails,
CaptureRC.EmailSubject,
"seen moving" + tag.ToString());
}
catch (AggregateException ex)
{
//TODO handle the error
//TODO log the erros, along with
}
}).Wait();
}
You should be making PrivateSignal
async
as well which includes marking it with async
and returning a Task
:
public override async Task PrivateSignalAsync(IEventInformation ev)
{
TagEvent tag = (TagEvent)ev;
try
{
await smptClient.SendMailAsync(CaptureRC.SmptFromEmailAddr, ToEmails, CaptureRC.EmailSubject, "seen moving" + tag.ToString());
}
catch (Exception ex)
{
// ...
}
}
It seems, though, that you can't do that since PrivateSignal
is overriding an already synchronous method. If you can change the base method to return a Task
then you should, but if you can't then simply don't use async
at all inside that method because blocking on async
can lead to deadlocks and other unwanted results:
public override void PrivateSignal(IEventInformation ev)
{
TagEvent tag = (TagEvent)ev;
try
{
smptClient.SendMail(CaptureRC.SmptFromEmailAddr, ToEmails, CaptureRC.EmailSubject, "seen moving" + tag.ToString());
}
catch (Exception ex)
{
// ...
}
}
async/await is the new hotness to replace things like Task.Run
and Task.Wait
. Try this:
public async override Task PrivateSignal(IEventInformation ev)
{
TagEvent tag = (TagEvent)ev;
try
{
await smptClient.SendMailAsync(CaptureRC.SmptFromEmailAddr,
ToEmails, CaptureRC.EmailSubject, "seen moving" + tag.ToString());
}
catch (Exception ex)
{
//TODO handle the error
//TODO log the erros, along with
}
}
The await
causes the running thread to suspend until the Task completes (or is cancelled or experiences an error). The rest of the method is registered as a continuation automatically. async/await is therefore syntactic sugar for task-based asynchronous programming.
Also, it's important to avoid async void
methods since the void
support is reserved for event handlers. Instead of void
, return Task
for methods with no return value.
Finally, since this method is an override
, you'd need to change the base method's return type to Task
as well.