2016-09-21 13 views
1

私はC#Hueアプリケーションで作業しています。私はAPIを作成して学習体験のために自分自身を呼び出しています。色相は多くのネットワークコールから構成されているので、私は作成したすべての同期メソッドに対して非同期メソッドも提供したいと考えていました。私はコードのいくつかの行を書いて、自分自身に "これはおそらくとても簡単なことではない"と思ったので、今ここにいるので、これが非同期関数を実装する良い方法であるかどうか尋ねたいと思っていましたか?また、私のコードに他の最適化をいただければ幸いです。非同期コードは簡単ですか?

using System.IO; 
using System.Net; 
using System.Threading.Tasks; 
using Newtonsoft.Json; 

namespace SharpHue 
{ 
    public class HueUtilities 
    { 
     const string DISCOVERY_URI = "http://www.meethue.com/api/nupnp"; 

     public struct DiscoveryElement 
     { 
      [JsonProperty("id")] 
      public string ID; 
      [JsonProperty("internalipaddress")] 
      public string Address; 
     } 

     public static DiscoveryElement[] DiscoverBridges() 
     { 
      string data = "[]"; 
      var request = WebRequest.CreateHttp(DISCOVERY_URI); 
      try 
      { 
       var response = request.GetResponse(); 
       using (var streamReader = new StreamReader(response.GetResponseStream())) 
       { 
        data = streamReader.ReadToEnd(); 
        streamReader.Close(); 
        response.Close(); 
       } 
       return JsonConvert.DeserializeObject<DiscoveryElement[]>(data); 
      } 
      catch (Exception ex) 
      { 
       throw ex; 
      } 
     } 

     public static async Task<DiscoveryElement[]> DiscoverBridgesAsync() 
     { 
      return await Task.Run(() => DiscoverBridges()); 
     } 
    } 
} 
+0

基本的に、すべてのIOコードを複製する必要があります。これは生産性とメンテナンスに重大な負担です。したがって、発信者が両方のスタイルを必要とするかどうかを考えてください。また、非同期で同期を使用して、同期パーセンテージラッパーをかなり小さなパーツコストで提供することもできます。 – usr

答えて

0

ほぼ。しかし、真の非同期の代替案があるときはTask.Runを避けるべきです。あなたは非同期呼び出しに同期呼び出しをラップする方法のためのより多くの使用はありません見ることができるように

public static async Task<DiscoveryElement[]> DiscoverBridgesAsync() 
{ 
    using (var client = new HttpClient()) 
    { 
     var result = await client.GetAsync(DISCOVERY_URI); 
     return await result.Content.ReadAsAsync<DiscoveryElement[]>();  
    } 
} 

:HttpClientをし、このようなあなたのコードを呼び出すとWebRequestクラスクラスを置き換える意味あなたの場合。これは真に非同期/準拠を待っています。

警告コンパイルエラーが発生することがありますが、うまくいくはずです。

さらに詳しい情報:http://www.asp.net/web-api/overview/advanced/calling-a-web-api-from-a-net-client

そして、これを読んでください:http://www.ben-morris.com/why-you-shouldnt-create-asynchronous-wrappers-with-task-run/

+0

これはうまく動作します:)これらのメソッドは並行して存在する必要があります。必要に応じてsyncを呼び出してasyncを呼び出すことができるはずです。同期方法も書き直すことをお勧めしますか? – Benedikt

+0

@Benedikt:これは非同期操作なので、非同期バージョンを保持することをお勧めします。しかし、**非同期/同期の両方のバージョンを維持する必要があり、コードの重複を避けたいのであれば、私の[brownfield async developmentに関する記事](https://msdn.microsoft)で "bool argument hack"をチェックしてください。 .com/en-us/magazine/mt238404.aspx)。 –

+0

@StephenCleary nice one!私のコードのためにそれを覚えています:-) –

0

ませんasyncコードは、彼らがasyncキーワードを追加した理由です書くこと難しいことで知らあります。問題は人々が何であるかを理解していない傾向がありますasyncコードは、なぜそれを使用しています。このコード

var result = await Task.FromResult(0); 

は文句を言わないので、それを作る非同期キーワードを使用して

Task.FromResult(0).ContinueWith((task)=> 
      { 
       var result = task.Result; 
      }); 

コードがある場合はないAsynchronousを書くことにsimilarです。あなたのコードは非同期キーワードではなく、Task.Runの量で非同期です。 ReadStreamReadstreamAsyncのようなものは、実際にはfile accessのように2つの全く異なることをするかもしれません。 AspはUIスレッドを持たないため、Task.RunはAsp.NetやWpfのように動作しません。また、タスクはスレッドとは無関係で、単一のスレッド上で実行でき、場合によっては実行できます。 Akavacheは、1つのスレッドで非同期プログラミングを行う方法の例です。バックグラウンドで何が行われるのかわからない場合は、asyncを使用してcarfulにする必要があります。

関連する問題