Reputation: 7136
(I am still in early stage of learning async-await
and Task Parallel Library.)
I was asked to add some functionality to our existing project: send out email notification when system gets important data.
// part of API; called by other parts of the program
public override void PrivateSignal(IEventInformation ev)
{
// ... some light CPU processing of data
// will do some IO bound (non-CPU bound) processing
// in my case, send out email notification
// using `System.Net.Mail.SmtpClient`class
smptClient.SendMail(CaptureRC.SmptFromEmailAddr,
ToEmails, CaptureRC.EmailSubject,
"seen moving" + tag.ToString());
}
According to answers to my previous questions and blog post by Stephen Cleary, following construct is not a good choice to make my code "asynchronous":
public override void PrivateSignal(IEventInformation ev) {
Task.Run(async ()=>{await smptClient.SendMailAsync(....);}).Wait();
}
Assume for the moment that PrivateSignal()
was called 50 times in a row, and I would make IO operation synchronous:
public override void PrivateSignal(IEventInformation ev) {
Task.Run(()=>{ smptClient.SendMail(....);}).WaitAll();
}
This will create 50 threads in the pool, and each one of them will be blocked by synchronous call, in addition, .WaitAll()
will block running thread (I can get rid of .WaitAll()
since return from SendMail() is void). Overall, 51 threads stuck, doing nothing.
What could be possible be done to improve IO operation without wasting so much time and resources ?
Upvotes: 0
Views: 206
Reputation: 456507
What could be possible be done to improve IO operation without wasting so much time and resources?
The best answer is to make PrivateSignal
asynchronous, just like the accepted answer to your last question suggested. Yes, this does mean that the base class has to change, and all the methods that call PrivateSignal
have to change. They have to change in order to enable asynchrony.
If you don't want to change PrivateSignal
, then PrivateSignal
is forced to be synchronous. And that forces you to use SendMail
, which blocks the thread. Because that's what synchronous means.
In order to be asynchronous, you must change PrivateSignal
so that it can be asynchronous.
(Side note in interest of full disclosure: it is possible to declare PrivateSignal
as an async void
method. However, this raises a whole host of problems. For details, see the "avoid async void" section of my MSDN article on async best practices or do a search on that phrase.)
Upvotes: 2
Reputation: 294287
Consider using an async SMTP client, like SmtpClient.SendAsync
:
Sends the specified e-mail message to an SMTP server for delivery. This method does not block the calling thread
Upvotes: 1