2016-09-21 6 views
1

Я работаю над приложением Cue Hue, я создаю собственные вызовы api для обучения. Поскольку Hue состоит из множества сетевых вызовов, я хотел также предоставить метод async для каждого метода синхронизации, который я создаю. Я написал несколько строк кода и подумал: «Это не может быть так просто», так что теперь я здесь и хотел спросить, является ли это хорошим способом реализации асинхронных функций? Также оцениваются любые другие оптимизации моего кода.Асинхронный код, который легко?

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

По существу, весь код ввода-вывода должен быть дублирован. Это является серьезной нагрузкой на производительность и обслуживание. Поэтому подумайте о том, нужны ли вызывающие/оба стиля. Вы также можете использовать sync over async, чтобы обеспечить удобные обертки для синхронизации с довольно небольшой начальной стоимостью. – usr

ответ

0

Практически. Но вы должны избегать Task.Run, когда есть настоящие асинхронные альтернативы. В вашем случае это означает, что заменяющий класс WebRequest с HttpClient и назвать код, как это:

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

Как вы можете видеть, там больше не использовать для метода, завернутых синхронный вызов на вызов асинхронного. Теперь он действительно асинхронный/ждущий.

warning Возможно, возникли некоторые ошибки компиляции, но они должны работать.

Подробнее: 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

Это работает просто отлично :) Эти методы должны существовать параллельно - вы должны иметь возможность вызывать синхронизацию и вызывать асинхронный вызов, когда это необходимо. Вы бы рекомендовали переписать метод синхронизации или оставить его? – Benedikt

+0

@Benedikt: Я рекомендую просто сохранить асинхронную версию, так как это операция async. Однако, если вы ** должны ** сохранять как версии async/sync, так и избегать дублирования кода, а затем проверить «hool-аргумент» в моей статье [статья о разработке асинхронного браузера] (https://msdn.microsoft .com/EN-US/журнал/mt238404.aspx). –

+0

@ StephenCleary хороший! будет помнить, что и для моего кода :-) –

0

Нет async код, как известно, трудно писать, поэтому они добавили async ключевое слово. проблема заключается в том, что люди не понимают, что такое код async и зачем его использовать. Этот код

var result = await Task.FromResult(0); 

ли similar писать

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

Если код не Asynchronous используя асинхронную ключевое слово не сделает это так. Ваш код является асинхронным из-за того, что доза Task.Run, а не асинхронное Ключевое слово. Такие вещи, как ReadStream и ReadstreamAsync, на самом деле могут сделать две совершенно разные вещи, например, с помощью file access. Task.Run не будет действовать одинаково в чем-то вроде Asp.Net и Wpf, так как доза asp не имеет нити пользовательского интерфейса. Также задачи не имеют ничего общего с потоками, которые они могут запускать в одном потоке и в некоторых случаях. Akavache - это пример того, как выполнять асинхронную программирование в одном потоке. Вы должны быть аккуратны, используя async, если вы не понимаете, что будет сделано в фоновом режиме.

Смежные вопросы