C#程序调用API时卡在GetAsync方法,无响应如何解决?
我需要在C# WPF程序中实现API接口查询功能。通过浏览器访问https://URI//api/clientnetwork/时,能得到如下响应:
{ "errors": [ "Invalid API key" ] }
这是因为缺少API密钥,但我希望程序至少能走到这一步。以下是我的代码:
using System; using System.Collections.Generic; using System.Linq; using System.Net.Http.Headers; using System.Net.Http; using System.Text; using System.Threading.Tasks; using System.Windows; using System.Windows.Controls; using System.Windows.Data; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Imaging; using System.Windows.Navigation; using System.Windows.Shapes; namespace ApiRequest { /// <summary> /// Interaktionslogik für MainWindow.xaml /// </summary> public partial class MainWindow : Window { public MainWindow() { InitializeComponent(); Get_Place("").Wait(); } static async Task Get_Place(string ip) { string path = "https://URI"; try { using (var client = new HttpClient()) { client.BaseAddress = new Uri(path); client.DefaultRequestHeaders.Accept.Clear(); client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json")); MessageBox.Show(path, "Path"); //Debug HttpResponseMessage response = await client.GetAsync("api/clientnetwork"); MessageBox.Show("fertig", "fertig"); //Debug if (response.IsSuccessStatusCode) { var jsonstring = response.Content.ReadAsStringAsync(); jsonstring.Wait(); //sto = JsonConvert.DeserializeObject<Standort>(jsonstring.Result); MessageBox.Show(jsonstring.ToString(), "Rückgabewert"); //Debug //sto = await response.Content.ReadAsAsync<Standort>(); - ReadAsAsync geht nicht } else { MessageBox.Show(response.StatusCode.ToString(), "Rückgabecode"); //Debug } } } catch (Exception ex) { MessageBox.Show(ex.ToString(), "Fehler:"); } } } }
我的程序在执行HttpResponseMessage response = await client.GetAsync("api/clientnetwork");这一行时卡住了,似乎一直在等待响应。请问我哪里出错了?
问题分析与解决方案
核心原因:UI线程死锁
你在窗口构造函数中调用了Get_Place("").Wait();,这会直接阻塞UI线程。而await client.GetAsync执行完成后,默认会尝试回到UI线程继续执行后续代码,但此时UI线程已经被.Wait()卡死,两边互相等待,最终造成死锁,导致程序卡在GetAsync步骤。
具体修复步骤
重构异步方法调用,避免阻塞UI线程
不要在构造函数中直接用.Wait()等待异步方法,改用窗口的Loaded事件异步调用:public MainWindow() { InitializeComponent(); Loaded += MainWindow_Loaded; } private async void MainWindow_Loaded(object sender, RoutedEventArgs e) { await Get_Place(""); }异步方法内统一使用
await,禁止.Wait()
读取响应内容时的.Wait()也可能引发类似阻塞问题,替换为await:if (response.IsSuccessStatusCode) { var jsonstring = await response.Content.ReadAsStringAsync(); MessageBox.Show(jsonstring, "Rückgabewert"); //Debug // sto = JsonConvert.DeserializeObject<Standort>(jsonstring); }校验API地址拼接一致性
浏览器访问的地址是https://URI//api/clientnetwork/,而你的代码拼接后是https://URI/api/clientnetwork,地址格式存在差异(多斜杠、末尾无斜杠)。虽然这不是卡死的直接原因,但可能影响API响应,建议调整GetAsync的参数:HttpResponseMessage response = await client.GetAsync("/api/clientnetwork/");关于
ReadAsAsync无法使用的说明ReadAsAsync属于System.Net.Http.Formatting命名空间,需要安装Microsoft.AspNet.WebApi.ClientNuGet包才能使用。如果不想额外安装包,当前使用ReadAsStringAsync配合Json.NET反序列化的方案是可行的。
内容的提问来源于stack exchange,提问作者Larian

