异步方法捕获异常后未返回值,导致LoadCollection无法完成的问题
问题原因与修复方案
核心问题:死锁导致方法无法完成
你的代码出现死锁的根源是在非UI线程调用了UI相关操作,具体逻辑如下:
DownloadCollectionAsync方法中使用了ConfigureAwait(false),这会让await之后的代码在非UI线程执行(脱离原同步上下文)。- 反序列化出错后,
catch块调用MessageBox.Show(ex.Message)——这个方法必须在UI线程才能正常执行,它会尝试切换回UI线程等待处理。 - 此时UI线程可能正卡在
LoadCollection的await HttpClientInstance.DownloadCollectionAsync(...)处,等待该Task完成,形成互相等待的死锁:非UI线程等UI线程处理弹窗,UI线程等非UI线程返回Task,最终两个线程都被阻塞,方法永远无法完成。
另外补充:Newtonsoft的Deserialize<T>方法虽然没有显式声明异常,但实际会抛出JsonReaderException、JsonSerializationException等运行时异常,你的代码捕获异常的逻辑本身没问题,但后续的弹窗操作触发了死锁。
修复方案
方案1:将UI操作移到UI线程执行
如果一定要在捕获异常时显示弹窗,需要手动切换回UI线程(以WPF为例):
public static async Task<Collections> DownloadCollectionAsync(Project activeProject) { HttpRequestMessage msg = new HttpRequestMessage { Method = HttpMethod.Get, RequestUri = new Uri(HttpClientInstance.BaseUri + "projects/get-collections/") }; msg.Headers.Add("projectID", $"{activeProject.Id}"); using (var response = await httpClient.SendAsync(msg, HttpCompletionOption.ResponseHeadersRead).ConfigureAwait(false)) { if (response.IsSuccessStatusCode) { try { using (Stream s = await response.Content.ReadAsStreamAsync()) using (StreamReader sr = new StreamReader(s)) using (JsonReader reader = new JsonTextReader(sr)) { JsonSerializer serializer = new JsonSerializer(); return serializer.Deserialize<Collections>(reader); } } catch (Exception ex) { // 切换到UI线程显示弹窗 Application.Current.Dispatcher.Invoke(() => MessageBox.Show(ex.Message)); } } } return null; }
方案2:将异常抛到上层UI方法处理(更推荐)
把非UI层的代码和UI操作解耦,让上层UI方法负责处理异常和弹窗:
// 修改DownloadCollectionAsync,移除UI操作,抛出异常或记录日志 public static async Task<Collections> DownloadCollectionAsync(Project activeProject) { HttpRequestMessage msg = new HttpRequestMessage { Method = HttpMethod.Get, RequestUri = new Uri(HttpClientInstance.BaseUri + "projects/get-collections/") }; msg.Headers.Add("projectID", $"{activeProject.Id}"); using (var response = await httpClient.SendAsync(msg, HttpCompletionOption.ResponseHeadersRead).ConfigureAwait(false)) { if (response.IsSuccessStatusCode) { using (Stream s = await response.Content.ReadAsStreamAsync()) using (StreamReader sr = new StreamReader(s)) using (JsonReader reader = new JsonTextReader(sr)) { JsonSerializer serializer = new JsonSerializer(); return serializer.Deserialize<Collections>(reader); } } } return null; } // 修改LoadCollection,在UI线程捕获异常并处理 internal async Task LoadCollection(Project activeProject) { try { Collections collections = await HttpClientInstance.DownloadCollectionAsync(activeProject); if (collections != null) { MyCollection = new ObservableCollection<WindowEntity>(collections.Collection.Select(x => x.Material).ToList()); } } catch (Exception ex) { MessageBox.Show(ex.Message); } }
这种方式更符合分层设计原则,避免了非UI代码依赖UI上下文,从根源上杜绝了此类死锁问题。
内容的提问来源于stack exchange,提问作者Ryan Daley
相关产品推荐
相关产品推荐

