【问题标题】:Task that has asynchronous IO operation具有异步 IO 操作的任务
【发布时间】: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 questionsblog 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


【解决方案1】:

如何在不浪费大量时间和资源的情况下改进 IO 操作?

最佳答案是使PrivateSignal 异步,就像accepted answer to your last question 建议的那样。是的,这确实意味着基类必须改变,所有调用PrivateSignal 的方法都必须改变。他们必须改变以启用异步。

如果您不想更改PrivateSignal,则PrivateSignal 被强制同步。这会迫使你使用SendMail,它会阻塞线程。因为这就是同步的意思

为了异步,您必须更改PrivateSignal,使其可以异步。

(关于全面披露的旁注:可能PrivateSignal 声明为async void 方法。但是,这会引发整个主机的问题. 详情见my MSDN article on async best practicesdo a search on that phrase的“避免异步无效”部分。)

【讨论】:

    【解决方案2】:

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

    将指定的电子邮件信息发送到 SMTP 服务器以进行传递。该方法不会阻塞调用线程

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-12-16
      相关资源
      最近更新 更多