具有异步IO操作的任务

时间:2015-02-11 05:49:22

标签: c# asynchronous task-parallel-library async-await task

(我还处于学习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();
}

假设暂时连续50次调用PrivateSignal(),我会使IO操作同步:

public override void PrivateSignal(IEventInformation ev) {
        Task.Run(()=>{ smptClient.SendMail(....);}).WaitAll();
    }

这将在池中创建50个线程,并且每个线程都将被同步调用阻塞,此外,.WaitAll()将阻止正在运行的线程(我可以从.WaitAll()中删除SendMail()无效)。总的来说,51个线程卡住了,什么都不做。

在不浪费大量时间和资源的情况下,可以做些什么来改进IO操作?

2 个答案:

答案 0 :(得分:2)

  

在不浪费大量时间和资源的情况下,可以做些什么来改进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的async void"部分。)

答案 1 :(得分:1)

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

  

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