我正在开发一个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());
}
}
}
答案 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剂量,而不是异步关键字。像ReadStream
和ReadstreamAsync
这样的东西实际上可能会做两个与file access完全不同的事情。
Task.Run不会像Asp.Net和Wpf那样表现相同,因为asp没有UI线程。此外,任务与它们可以在单个线程上运行的线程无关,并且在某些情况下也可以。Akavache是如何在单个线程上执行异步编程的示例。如果您不了解将在后台完成的工作,您必须使用异步工具。