2016-09-28 11 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が安全ではない(プロセス全体がクラッシュする可能性がある)と思われ、イベントハンドラ専用に設計されているようです。同期void関数はasync Taskに変換する必要がありますが、ここでもfire-and-forgot関数が必要です。 これが真の場合、強制的にタスクを返すには、Task.Run(() => {...})の中にコード全体をカプセル化する必要があります。返すTaskオブジェクトについては本当に気にしないので、冗長で奇妙に見えますが、コンパイラは文句を言うでしょう。 私の場合、それを書き換えるための推奨される方法は何ですか?ありがとう。

答えて

2

そのawaitable XXXAsyncのカウンターパートと、すべての同期の.NETライブラリ関数を交換し、あなたは少しここでの手順を変更する場合、変更関数のシグネチャ

は実際に、それは少し簡単です:

  1. 置き換えすべての同期APIは*Async相当になります。
  2. await

コンパイラがインクルードはあなたに(この場合、async Taskで)あなたのための正しい署名を示唆エラーを与えるでしょう。

強制的にタスクを返すために、私は全然Task.Run

内全体のコードをカプセル化する必要があります。 asyncキーワードはTaskとなります。

補足として、Writeコールは安全ではありません。ストリーム(特にネットワークストリーム)は部分バッファのみを書き込むことが可能です。

+0

ありがとうスティーブン!あなたの本とあなたのブログはとても役立ちます。あなたの提案に従って、署名がasyncキーワードであることがわかりました。タスクを作成して返すためにTask.Runを明示的に呼び出す必要はありません。私は2つの質問があります:(1)今コンパイラが私の新しい関数SendToUrlAsyncを待つべきであると不満を言っています。もし私がfire-and-forgetの振る舞いをしたいのであれば、どうしたらいいですか? (2)Stream.Write/Stream.WriteAsyncについてもう少し説明できますか?この方法でリクエストストリームを使用するサンプルが多数見られましたが、正しくない場合は、データを投稿する正しい方法は何ですか? Tks! – codewarrior

+0

呼び出し元がSendToUrlAsyncと呼ばれるときに私は追加しようとしましたが、コンパイラは呼び出し側を非同期タスクに変更する必要があると言いました。私はすぐに私はこのコールチェーンのすべての関数を非同期タスクに変更する必要があることがわかります、それは良い方法ですか? – codewarrior

+0

@codewarrior:理想的には、 'async'を成長させるべきです。 1)火災と忘れをする(ほとんどの場合は間違っている)(http://blog.stephencleary.com/2014/06/fire-and-forget-on-asp-net.html))、 var _ = SendToUrlAsync(); '。 2) 'BinaryWriter'を使うか、' MemoryStream'に入れて 'CopyToAsync'を呼び出します。 –

関連する問題