【发布时间】:2019-06-11 00:09:38
【问题描述】:
最初,我创建了一个控制台应用程序来进行一些测试,从服务器获取 api 调用,并获得了完整的功能和工作。现在,我想进行显示,但是来自控制台应用程序的完全相同的代码在 winforms 应用程序中不起作用。由于一些断点测试,我看到它挂在这一行:
var response = await httpClient.SendAsync(request);
我不明白有什么区别,我已经下载了所有必要的包。我认为这与使用等待有关。谢谢,伊森
这里是排除私有信息的请求方法代码。我意识到最后有一些不必要的组件,但我只是从我最初的测试控制台应用程序中复制和粘贴。使用此方法的所有方法,包括 main,都是异步的。
public async Task<string> APICall(string address)
{
string error = "An error was encountered.";
using (var httpClient = new HttpClient())
{
using (var request = new HttpRequestMessage(new HttpMethod("GET"), address))
{
request.Headers.TryAddWithoutValidation("Api-Key", "API KEY");
httpClient.DefaultRequestHeaders.Accept.Add(
new MediaTypeWithQualityHeaderValue("application/hal+json"));
var response = await httpClient.SendAsync(request);
if (response.IsSuccessStatusCode)
{
try
{
Stream res = await response.Content.ReadAsStreamAsync();
var serializer = new JsonSerializer();
using (var sr = new StreamReader(res))
{
using (var jsonTextReader = new JsonTextReader(sr))
{
return await response.Content.ReadAsStringAsync();
}
}
}
catch (IOException e)
{
Console.WriteLine(e);
}
catch (NullReferenceException e)
{
Console.WriteLine(e);
}
}
request.Dispose();
}
httpClient.Dispose();
}
return error;
}
这些是调用问题方法的调用方法,它从 Main 到 startAsync 再到 CallAsync,再到 APICall,即相关方法。
static async Task Main(string[] args)
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Form1 f = new Form1();
Caller caller = new Caller();
string test = await caller.CallAsync();
foreach (KeyValuePair<string, Server> server in Server.servers)
{
f.AddRow(server.Value.name, server.Value.location, server.Value.status, server.Value.ticketStatus);
}
Application.Run(f);
}
public static async Task startAsync()
{
Caller caller = new Caller();
string json = await caller.CallAsync();
Console.WriteLine(json);
dynamic name = JsonConvert.DeserializeObject<RootObject>(json);
List<Location> locs = name._embedded.locations;
int count = 0;
foreach (Location loc in locs)
{
count++;
Console.WriteLine(count);
Server.servers.Add(loc.name, new Server(loc.name, loc.address.city, loc.address.state, loc.id, loc.status, await caller.TicketStatusAsync(loc.id)));
}
}
public async Task<string> CallAsync()
{
return await APICall(baseAddress);
}
【问题讨论】:
-
您在控制台应用中收到响应了吗?
-
请提供更多关于代码的上下文。控制台应用程序调用它的方式与 WinForms 应用程序有什么区别?
request是如何构造的,它包含什么? -
只是猜测......你有一个deadlock
-
我猜测某些方法直接或间接(通过其他方法)调用您的方法不是使用 await 而是使用
Wait()或Result。这将阻塞调用任务(通常是 UI 任务),因此 await 无法切换回导致死锁的 UI 任务。这不会在控制台中发生,因为它们没有同步上下文(UI 线程)可以切换回来。 -
如果没有看到您的方法和调用方法,我不能肯定地说,但是您可以使用
SendAsync(…).ConfigureAwait(false)来避免上下文切换。但实际上,async 本来就是异步的,应该避免调用 Wait/Result。