我不熟悉async/await
的工作原理。为了更好地理解它,我在下面创建了一个示例代码:
static void Main(string[] args)
{
GetAPI();
Console.WriteLine("Hello");
Console.ReadLine();
}
public static async void GetAPI()
{
using (HttpClient client = new HttpClient())
{
client.DefaultRequestHeaders.Add("Get", "application/json");
var response = await client.GetAsync("http://somelinks");
string content = await response.Content.ReadAsStringAsync();
Console.WriteLine(content);
Console.ReadLine();
}
}
GetAPI()
方法基本上会调用一个以Json
格式返回某些内容的API。但是,我收到的输出是......令人惊讶的,尽管首先调用GetAPI()
,但首先在控制台中打印“Hello”。当我设置调试器时,在它到达await
中的GetAPI()
之后,它似乎就会回到Main
。
如何首先从API打印内容?换句话说,我如何确保程序首先执行GetAPI()
中的所有内容?
其他信息:
async/await
,因为HttpClient
仅提供GetAsync
方法。async/await
中使用Main
。它给我一个错误说Error 1 'ConsumeWebApi.Program.Main(string[])': an entry point cannot be marked with the 'async' modifier
答案 0 :(得分:1)
您应该从我认为的异步方法返回任务。
然后你可以等待返回,如下:
static void Main(string[] args)
{
GetAPI().Wait();
Console.WriteLine("Hello");
Console.ReadLine();
}
public static async Task GetAPI()
{
using (HttpClient client = new HttpClient())
{
client.DefaultRequestHeaders.Add("Get", "application/json");
var response = await client.GetAsync("http://google.com/");
string content = await response.Content.ReadAsStringAsync();
Console.WriteLine(content);
Console.ReadLine();
}
}
答案 1 :(得分:1)
您有两个选项可以为您提供所需的行为:
如果您的目标只是让这个调用同步,以便您的console.write打印,以便您可以从方法声明中删除异步,不要使用await和do .result,如下所示:
private void LoadData()
{
using (HttpClient client = new HttpClient())
{
client.DefaultRequestHeaders.Accept.Add(
new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/json"));
var response = client.GetAsync("http://somelinks").Result;
string content = response.Content.ReadAsStringAsync().Result;
Console.WriteLine(content);
Console.ReadLine();
}
}
您的http标头请求json不正确您有一个名为'get'的标题。
如果要进行异步调用,则需要从异步方法调用它或使用wait等待它完成。通常在事件处理程序中,您只需将事件处理程序标记为异步,并确保从异步方法返回一种Task。
在像您的情况一样的控制台程序中,您可以等待异步方法。您需要从异步方法返回类型任务而不是像您一样无法等待它。这将允许您在完成并移动到WriteLine之前等待异步方法完成。尽管如此,它仍然可以实现同步,并且这两种方法在您的控制台应用程序中的行为相同。
static void Main(string[] args)
{
Console.WriteLine("here");
LoadData().Wait();
Console.WriteLine("there");
}
static async private Task LoadData()
{
using (HttpClient client = new HttpClient())
{
client.DefaultRequestHeaders.Accept.Add(
new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/json"));
var response = await client.GetAsync("http://somelinks");
string content = await response.Content.ReadAsStringAsync();
Console.WriteLine(content);
Console.ReadLine();
}
}
一般情况下,最好将方法保留为异步,因为如果将其移动到程序使用的共享库中,该程序可以从需要它的async方法中受益,并在需要的位置同步比如你的控制台应用程序。你最终能够这样做。
答案 2 :(得分:0)
建议的答案是在从Main()调用async方法时使用.Wait()。 E.g。
// call this async method and wait for it to finish
GetApi().Wait();
// do something that should only happen when the async method is over
await / async技术创建了一些后台工作,在等待某事之前无需同步。很明显,OP希望在继续之前等待GetAPI完成,并且主要方法可能不希望退出仍在继续的工作。
答案 3 :(得分:-1)
我还在学习这个(2周前有这个,但是讲师告诉我们,如果它有效,我们使用一些控件很重要。
我不知道它是否会帮助你,但我可以尝试编写我们已经学会使用的代码:
如果您在代码中实现它并根据需要进行更改,则可能会有效。
首先,您的返回类型应始终以Task开头(如果我的讲师是对的)
public async static Task<List<string>> Test()
{
using (var client = new HttpClient())
{
client.BaseAddress = new Uri(@"http://thebaseadres.net/api/");
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(
new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/json"));
HttpResponseMessage response = await client.GetAsync("lastbitofurl");
if (response.IsSuccessStatusCode)
{
string s = await response.Content.ReadAsStringAsync();
List<String> test = JsonConvert.DeserializeObject<List<string>>(s);
return test;
}
else
return null;
}
}
修改强>
你说你因为主要内容而被迫使用异步,但是你不能在mainpage_loaded上输入你的GetApi()方法吗?
这样的事情:
async void MainPage_Loaded(object sender, RoutedEventsArgs e)
{
await GetAPI();
}