具有异步IO操作的任务

Task that has asynchronous IO operation

(我还在早期学习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 对我的 and 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() 的 return 无效)。总的来说,有 51 个线程卡住了,什么也没做。

如何才能在不浪费太多时间和资源的情况下改进 IO 操作?

考虑使用异步 SMTP 客户端,例如 SmtpClient.SendAsync:

Sends the specified e-mail message to an SMTP server for delivery. This method does not block the calling thread

What could be possible be done to improve IO operation without wasting so much time and resources?

最佳 答案是使 PrivateSignal 异步,就像 所建议的那样。是的,这确实意味着基 class 必须改变,所有调用 PrivateSignal 的方法都必须改变。他们需要进行更改以启用异步。

如果不想改变PrivateSignal,那么PrivateSignal就强制同步。这会迫使您使用 SendMail,它会阻塞线程。因为这就是同步 的意思 .

为了异步,您必须更改PrivateSignal以便它可以异步。

(为了全面披露而附注:可能PrivateSignal 声明为 async void 方法。但是,这会引发 整个主机 的问题。有关详细信息,请参阅 my MSDN article on async best practices or do a search on that phrase 的 "avoid async void" 部分。)