异步代码容易吗?

时间:2016-09-21 16:36:48

标签: c# asynchronous async-await

我正在开发一个C#Hue应用程序,我正在创建api调用以获得学习体验。由于Hue包含许多网络调用,我还想为我创建的每个同步方法提供异步方法。我写了一些代码并且自己想“这可能不那么容易”,所以现在我在这里想问这是否是实现异步函数的好方法?我对代码的任何其他优化都表示赞赏。

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());
        }
    }
}

2 个答案:

答案 0 :(得分:0)

几乎。但是当存在真正的异步备选方案时,您应该避免使用Task.Run。在你的情况下,这意味着用HttpClient替换WebRequest类并调用你的代码:

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

正如您所看到的,将同步调用包装到异步调用的方法不再有用。它现在真的是异步/等待兼容。

警告可能存在一些编译错误但应该有效。

更多信息: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/

答案 1 :(得分:0)

众所周知,没有async代码很难写出他们添加async关键字的原因。问题往往是人们不了解async代码是什么以及为什么要使用它。这段代码

var result = await Task.FromResult(0);

similar是否写作

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

如果代码不是Asynchronous使用async关键字,请不要这样做。您的代码是异步的,因为Task.Run剂量,而不是异步关键字。像ReadStreamReadstreamAsync这样的东西实际上可能会做两个与file access完全不同的事情。 Task.Run不会像Asp.Net和Wpf那样表现相同,因为asp没有UI线程。此外,任务与它们可以在单个线程上运行的线程无关,并且在某些情况下也可以。Akavache是如何在单个线程上执行异步编程的示例。如果您不了解将在后台完成的工作,您必须使用异步工具。