.NET Framework4.8控制台调试GraphQL.SendQueryAsync时程序莫名终止求助
问题原因分析
- 主线程未等待异步方法完成:
Main是同步方法,调用异步的TryMe()时未等待其执行完毕,主线程直接运行到末尾并退出,导致异步请求还没完成程序就终止,控制流“消失”且异常无法被捕获(主线程已结束)。 - 反序列化模型不匹配:GraphQL查询返回的是
countries数组,而当前用单个Country类接收,后续即使解决线程问题,也会出现反序列化失败的异常。
解决办法
方法1:在同步Main中等待异步方法完成
在Main方法中调用异步方法的GetAwaiter().GetResult()(避免AggregateException包装原始异常),阻止主线程提前退出。
方法2:使用异步Main方法(需C# 7.1+)
将Main改为async static Task类型,直接await异步方法,这是更规范的异步写法,需确保项目C#语言版本设置为7.1或更高(项目属性→生成→高级→语言版本)。
修正反序列化模型
创建包含countries数组的根对象类,匹配GraphQL返回的数据结构。
修改后的完整代码
方法1(同步Main等待)
using GraphQL; using GraphQL.Client.Http; using GraphQL.Client.Serializer.Newtonsoft; using System; using System.Collections.Generic; using System.Threading.Tasks; namespace ConsoleApp3 { class Program { static void Main(string[] args) { Program myObj = new Program(); // 等待异步方法完成,保留原始异常信息 myObj.TryMe().GetAwaiter().GetResult(); } public async Task TryMe() { var graphQLClient = new GraphQLHttpClient(new GraphQLHttpClientOptions { EndPoint = new Uri("https://countries.trevorblades.com/") }, new NewtonsoftJsonSerializer()); try { var request = new GraphQLHttpRequest { Query = "query{countries{name,capital,code,currency}}" }; // 使用匹配返回结构的根对象接收数据 GraphQLResponse<CountryResponse> response = await graphQLClient.SendQueryAsync<CountryResponse>(request); // 输出测试结果 foreach (var country in response.Data.countries) { Console.WriteLine($"国家:{country.name},首都:{country.capital}"); } } catch (Exception ex) { Console.WriteLine($"异常信息:{ex.Message}"); throw; } finally { // 释放客户端资源 await graphQLClient.DisposeAsync(); } } } // 根对象类,匹配GraphQL返回的countries数组结构 public class CountryResponse { public List<Country> countries { get; set; } } public class Country { public string name { get; set; } public string capital { get; set; } public string code { get; set; } public string currency { get; set; } } }
方法2(异步Main)
using GraphQL; using GraphQL.Client.Http; using GraphQL.Client.Serializer.Newtonsoft; using System; using System.Collections.Generic; using System.Threading.Tasks; namespace ConsoleApp3 { class Program { // 改为异步Main方法 static async Task Main(string[] args) { Program myObj = new Program(); await myObj.TryMe(); } public async Task TryMe() { var graphQLClient = new GraphQLHttpClient(new GraphQLHttpClientOptions { EndPoint = new Uri("https://countries.trevorblades.com/") }, new NewtonsoftJsonSerializer()); try { var request = new GraphQLHttpRequest { Query = "query{countries{name,capital,code,currency}}" }; GraphQLResponse<CountryResponse> response = await graphQLClient.SendQueryAsync<CountryResponse>(request); foreach (var country in response.Data.countries) { Console.WriteLine($"国家:{country.name},首都:{country.capital}"); } } catch (Exception ex) { Console.WriteLine($"异常信息:{ex.Message}"); throw; } finally { await graphQLClient.DisposeAsync(); } } } public class CountryResponse { public List<Country> countries { get; set; } } public class Country { public string name { get; set; } public string capital { get; set; } public string code { get; set; } public string currency { get; set; } } }
额外注意事项
- 确保项目已正确安装依赖包:
GraphQL.Client(5.1.1.0)、GraphQL.Client.Serializer.Newtonsoft(5.1.1.0)、Newtonsoft.Json(13.0.0.0)。 - 使用
finally块释放GraphQLHttpClient资源,避免内存泄漏。 - 若用异步Main,需在项目属性中设置C#语言版本为7.1或更高。
内容的提问来源于stack exchange,提问作者Shriram Karpur
相关产品推荐
相关产品推荐

