2016-09-28 82 views
0

它可能是一個愚蠢的問題。我正在用TAP重寫同步HTTP發送數據函數以異步。 功能如下:正確的方式來重寫同步功能與TAP

public void SendToUrl(string url, string content) 
{ 
    try 
    { 
     byte[] payload = Encoding.ASCII.GetBytes(content); 
     Stopwatch sw = Stopwatch.StartNew(); 
     HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url); 
     request.Method = "POST"; 
     request.ContentType = "text/plain"; 
     request.ContentLength = payload.Length; 

     using (Stream stream = request.GetRequestStream()) 
     { 
      stream.Write(payload, 0, payload.Length); 
     } 

     using (HttpWebResponse response = (HttpWebResponse)request.GetResponse()) 
     { 
      sw.Stop(); 
      if (response.StatusCode == HttpStatusCode.OK || response.StatusCode == HttpStatusCode.Accepted) 
      { 
       .... 
      } 
      else 
      { 
       .... 
      } 
     } 
    } 
    catch // error handling omitted 
    { 
    } 
} 

起初,我認爲這是非常簡單的,只需更換與他們awaitable XXXAsync同行和變化的函數簽名的所有同步.NET庫函數來public async void SendToUrlAsync(...)(因爲我用等待着裏面的函數),但是,在閱讀了一些文章之後,看起來好像很多人說async void不安全(可能會導致整個進程崩潰),而且它僅用於事件處理程序。同步無效函數應該被翻譯成async Task,即使我想在這裏有一個失火和遺忘的函數。 如果這是真的,爲了強制返回一個任務,我需要封裝整個代碼Task.Run(() => {...})這看起來像多餘和奇怪,因爲我真的不關心返回任務對象,但如果我不等待它編譯器會抱怨。 那麼,在我的情況下,推薦重寫它的方法是什麼?謝謝。

回答

2

與他們awaitable XXXAsync同行和變化的函數簽名替換所有同步.NET庫函數

其實,如果你稍微修改此處的步驟,這是一個有點簡單:

  1. 更換所有同步API與他們的*Async等效。
  2. await他們。

編譯器會在給你暗示適合你的正確的簽名(在這種情況下,async Task)錯誤

強行返回一個任務,我需要一個Task.Run

一點也不內封裝整個代碼。 async關鍵字將爲您創建一個Task

在附註中,Write調用是不安全的 - 流(特別是網絡流)可能只寫入部分緩衝區。

+0

謝謝Stephen!你的書和你的博客是超級有用的。我遵循你的建議,並發現你是正確的,在簽名中使用async關鍵字,我不需要顯式調用Task.Run來創建並返回任務,很高興能夠學習這一點。我有兩個問題:(1)現在,編譯器抱怨說我應該等待我的新函數SendToUrlAsync,如果我確實想要失控行爲,我該怎麼辦? (2)你能解釋一下關於Stream.Write/Stream.WriteAsync的更多信息嗎?我看到很多以這種方式使用請求流的示例,如果它不正確,發佈數據的正確方法是什麼? TKS! – codewarrior

+0

我試圖在調用者調用SendToUrlAsync時添加await,現在編譯器說我需要將調用者更改爲異步Task。我可以看到,很快我需要將此調用鏈中的每個函數都改爲異步任務,這是一個好方法嗎? – codewarrior

+0

@codewarrior:理想情況是,你應該讓'async'成長。 1)要做到隨心所欲(這是[幾乎總是錯](http://blog.stephencleary.com/2014/06/fire-and-forget-on-asp-net.html)),做' var _ = SendToUrlAsync();'。 2)使用'BinaryWriter'或將其放入'MemoryStream'並調用'CopyToAsync'。 –