【发布时间】:2015-02-11 19:16:53
【问题描述】:
(我还处于学习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();
}
暂时假设PrivateSignal()被连续调用50次,我会让IO操作同步:
public override void PrivateSignal(IEventInformation ev) {
Task.Run(()=>{ smptClient.SendMail(....);}).WaitAll();
}
这将在池中创建50个线程,每个线程都会被同步调用阻塞,另外,.WaitAll()将阻塞正在运行的线程(我可以摆脱.WaitAll(),因为从SendMail()返回是空白)。总共有 51 个线程卡住了,什么也没做。
在不浪费大量时间和资源的情况下,可以做些什么来改进 IO 操作?
【问题讨论】:
-
你为什么用
Task.Run(async ()=>{await smptClient.SendMailAsync(....);}).Wait()而不是smptClient.SendMailAsync(....).Wait(),或者干脆用smptClient.Send()?它们都阻塞了调用线程。另外,PrivateSignal真的需要等待邮件发送完毕,还是可以直接发起发送并返回给调用者?
标签: c# asynchronous task-parallel-library async-await task