2015-02-10 95 views
2

的異步/等待代碼我讀async-await功能的文檔,但仍然高度混淆如何構造async-await代碼,調用SmtpClient.SendMailAsync()方法。
我應該如何重寫代碼才能正確使用async-await困惑於如何構造調用SmtpClient.SendMailAsync()

目前,我的代碼如下所示:
定期由系統調用PrivateSignal發送電子郵件通知。

public override void PrivateSignal(IEventInformation ev) 
{ 
    TagEvent tag = (TagEvent)ev; 
    Task.Run(async() => 
    { 
     try 
     { 
      await smptClient.SendMailAsync(CaptureRC.SmptFromEmailAddr, 
            ToEmails, 
            CaptureRC.EmailSubject, 
            "seen moving" + tag.ToString()); 
     } 
     catch (AggregateException ex) 
     { 
      //TODO handle the error 
      //TODO log the erros, along with 
     } 
    }).Wait(); 
} 

回答

4

你應該做PrivateSignalasync以及包括與async標記,並返回一個Task

public override async Task PrivateSignalAsync(IEventInformation ev) 
{ 
    TagEvent tag = (TagEvent)ev; 
    try 
    { 
     await smptClient.SendMailAsync(CaptureRC.SmptFromEmailAddr, ToEmails, CaptureRC.EmailSubject, "seen moving" + tag.ToString()); 
    } 
    catch (Exception ex) 
    { 
     // ... 
    } 
} 

看來,雖然,你不能這樣做,因爲PrivateSignal是壓倒已經同步方法。如果你可以改變基本方法返回一個Task那麼你應該,但如果你不能那麼簡單地不使用async在所有的方法中,因爲阻塞async可能導致死鎖和其他不想要的結果:

public override void PrivateSignal(IEventInformation ev) 
{ 
    TagEvent tag = (TagEvent)ev; 
    try 
    { 
     smptClient.SendMail(CaptureRC.SmptFromEmailAddr, ToEmails, CaptureRC.EmailSubject, "seen moving" + tag.ToString()); 
    } 
    catch (Exception ex) 
    { 
     // ... 
    } 
} 
+1

smptClient.SendMail()不應拋出AggregateException。 AggregateException是TPL(任務,任務等)方法拋出的。 – 2015-02-10 22:30:45

+1

@TimGoyer true。更新。 – i3arnon 2015-02-10 22:32:08

+0

讓我們假設我可以將代碼更改爲異步,就像您擁有它的方式一樣。 1.如何從其他函數調用此方法? '等待PrivateSignal(標籤)'或'Task.Run(()=> PrivateSignal(標籤)).Await()'? 2.調用方法是否也是「異步」的? – newprint 2015-02-10 23:57:14

1

異步/ AWAIT是新的辣味來代替像Task.RunTask.Wait事情。試試這個:

public async override Task PrivateSignal(IEventInformation ev) 
{ 
    TagEvent tag = (TagEvent)ev; 

    try 
    { 
     await smptClient.SendMailAsync(CaptureRC.SmptFromEmailAddr, 
      ToEmails, CaptureRC.EmailSubject, "seen moving" + tag.ToString()); 
    } 
    catch (Exception ex) 
    { 
     //TODO handle the error 
     //TODO log the erros, along with 
    } 
} 

await導致正在運行的線程暫停,直到任務完成(或取消或遇到錯誤)。該方法的其餘部分自動註冊爲延續。 async/await因此是基於任務的異步編程的語法糖。

此外,避免async void方法很重要,因爲void支持保留給事件處理程序。對於沒有返回值的方法,請返回Task而不是void

最後,由於此方法是override,所以您還需要將基本方法的返回類型更改爲Task

+3

該基地只需要一個「任務」。 '異步'只是如果它實際上是異步的... – i3arnon 2015-02-10 22:28:10

+0

@ i3arnon啊,好點。 – Haney 2015-02-10 22:45:07