异步爬虫构造函数未获值、ShowCast打印失败及修改后报错问题
问题1:构造函数中Console.WriteLine(show.Name)无输出及ShowCast无法打印PersonId的原因
核心原因:
异步方法未等待导致数据未加载:
构造函数中直接调用CrawlShowAsync和CrawlcastAsync这类异步方法,但构造函数不支持async,调用时未使用await,导致构造函数执行完毕时,HTTP请求仍在后台运行,此时show.Name和cast.dataCast都未被赋值,自然无输出。类设计冗余且赋值错误:
Show类中定义了嵌套的public Show show { get; set; }属性,反序列化后的数据被赋值给了这个嵌套属性,而非当前实例的ShowId和Name。你打印的是外层show.Name(当前实例的Name),而非嵌套的show.show.Name,所以值为null。未初始化集合导致空引用异常:
ShowCast类的CastIds集合未在构造函数中初始化(比如CastIds = new List<long>();),调用CastIds.Add时会直接抛出NullReferenceException,阻止后续代码执行。
问题2:修改后Console.WriteLine(show.Name)仍无输出及showCast.start()报错的原因
核心原因:
数据赋值目标错误:
修改后的Show.CrawlShowAsync依然把反序列化结果赋值给嵌套的show属性,而非当前实例的ShowId和Name。当前实例的Name始终为null,自然无法输出。方法调用对象错误:
showCast.start()报错是因为ShowCast类根本没有定义start方法,这个方法属于Crawler类,你混淆了调用对象。异步方法调用未等待:
Crawler.start方法中调用CrawlShow(show, cast)时未加await,会导致该异步方法在后台运行,无法保证执行顺序。反序列化属性映射错误:
TVMaze的cast接口返回的JSON中,演员数据在person字段下,但Cast类的Person属性没有添加[JsonProperty("person")]特性,导致反序列化失败,Person属性始终为null。
关键修正建议示例
修正Show类:
class Show { [JsonProperty("id")] public long ShowId { get; set; } [JsonProperty("name")] public string Name { get; set; } // 移除冗余的嵌套show属性 public Show() { } public async Task LoadShowAsync(long showId) { using HttpClient client = new HttpClient(); string url = $"https://api.tvmaze.com/shows/{showId}"; string response = await client.GetStringAsync(url); var result = JsonConvert.DeserializeObject<Show>(response); // 将数据赋值给当前实例的属性 this.ShowId = result.ShowId; this.Name = result.Name; } }
修正Cast类:
class Cast { [JsonProperty("person")] // 加上JsonProperty匹配接口字段 public Person? Person { get; set; } public static async Task<List<Cast>> LoadCastsAsync(long showId) { using HttpClient client = new HttpClient(); string urlcast = $"https://api.tvmaze.com/shows/{showId}/cast"; string responseCast = await client.GetStringAsync(urlcast); return JsonConvert.DeserializeObject<List<Cast>>(responseCast); } }
修正ShowCast类:
class ShowCast { public long ShowId { get; set; } public List<long> CastIds { get; set; } public ShowCast(Show show, List<Cast> casts) { this.ShowId = show.ShowId; CastIds = new List<long>(); // 初始化集合 foreach(var item in casts) { if(item.Person != null) { Console.WriteLine(item.Person.PersonId); CastIds.Add(item.Person.PersonId); } } } }
修正Crawler类:
class Crawler { public Show show { get; set; } public ShowCast showCast { get; set; } public Crawler() { show = new Show(); } public async Task StartAsync(long showId) { await show.LoadShowAsync(showId); var casts = await Cast.LoadCastsAsync(showId); Console.WriteLine(show.Name); // 此时Name已被赋值 showCast = new ShowCast(show, casts); } }
修正Main方法:
public static async Task Main() { Crawler crawler = new Crawler(); await crawler.StartAsync(530); Console.WriteLine("End of Code"); Console.ReadKey(); }
内容的提问来源于stack exchange,提问作者jennifer ruurs

