(我还处于学习async-await
和任务并行库的早期阶段。)
我被要求在现有项目中添加一些功能:在系统获取重要数据时发送电子邮件通知。
// 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());
}
根据Stephen Cleary的previous questions和blog post的答案,以下构造不是制作我的代码的好选择"异步":
public override void PrivateSignal(IEventInformation ev) {
Task.Run(async ()=>{await smptClient.SendMailAsync(....);}).Wait();
}
假设暂时连续50次调用PrivateSignal()
,我会使IO操作同步:
public override void PrivateSignal(IEventInformation ev) {
Task.Run(()=>{ smptClient.SendMail(....);}).WaitAll();
}
这将在池中创建50个线程,并且每个线程都将被同步调用阻塞,此外,.WaitAll()
将阻止正在运行的线程(我可以从.WaitAll()
中删除SendMail()无效)。总的来说,51个线程卡住了,什么都不做。
在不浪费大量时间和资源的情况下,可以做些什么来改进IO操作?
答案 0 :(得分:2)
在不浪费大量时间和资源的情况下,可以做些什么来改进IO操作?
最佳答案是让PrivateSignal
异步,就像建议的accepted answer to your last question一样。是的,这确实意味着必须更改基类,并且所有调用PrivateSignal
的方法都必须更改。他们要进行更改才能启用异步。
如果您不想更改PrivateSignal
,则PrivateSignal
会被迫同步。这迫使你使用SendMail
来阻止线程。因为那是同步意味着。
为了实现异步,必须更改PrivateSignal
,以便它可以是异步的。
(有关完全披露的附注:可能可能将PrivateSignal
声明为async void
方法。但是,这会引发整个主机强烈的>问题。有关详情,请参阅"避免my MSDN article on async best practices或do a search on that phrase的async void"部分。)
答案 1 :(得分:1)
考虑使用异步SMTP客户端,例如SmtpClient.SendAsync
:
将指定的电子邮件发送到SMTP服务器以进行传递。此方法不会阻止调用线程