ViewModel加载时异步方法调用致应用崩溃,async void转async Task存疑
解决异步更新检查时应用崩溃/卡死的问题
核心问题:async void的隐患
async void仅适用于事件处理程序,非场景下使用会导致异常无法被常规捕获,直接引发应用崩溃或卡死——这正是你当前遇到的问题。另外纠正误解:async Task不需要返回值,它就是专门用于无返回结果的异步方法,Task<T>才需要返回对应类型的值。
具体修改方案
1. 重构CheckForUpdatesExecute方法
将async void改为async Task,并添加异常捕获逻辑,避免未处理异常导致崩溃:
private async Task CheckForUpdatesExecute() { try { var latestVersionFull = await GetLatestVersionAsync(); // 更安全的版本号处理:判断前缀后再截取,避免非v开头的标签解析失败 var latestVersionStr = latestVersionFull.StartsWith("v") ? latestVersionFull.Substring(1) : latestVersionFull; if (Version.TryParse(latestVersionStr, out var latestVersion)) { _updatesAvailable = latestVersion > CurrentVersion; ((DelegateCommand)InstallUpdate).RaiseCanExecuteChanged(); } else { // 版本解析失败时的降级处理 _updatesAvailable = false; } } catch (Exception ex) { // 可在此添加日志记录等异常处理逻辑 _updatesAvailable = false; } }
2. 优化HttpClient的使用
频繁创建HttpClient会耗尽HTTP连接池,导致请求卡死。改成静态单例复用:
// 静态HttpClient实例,全局复用 private static readonly HttpClient _httpClient = new HttpClient(); // 在ViewModel静态构造函数中初始化请求头 static YourViewModel() { _httpClient.DefaultRequestHeaders.Accept.TryParseAdd("application/vnd.github+json"); _httpClient.DefaultRequestHeaders.UserAgent.TryParseAdd("Test"); } private async Task<string> GetLatestVersionAsync() { try { var stream = await _httpClient.GetStreamAsync("https://api.github.com/repos/<ORG>/<REPO>/releases/latest"); // 使用using确保JsonDocument资源被及时释放 using var document = await JsonDocument.ParseAsync(stream); if (document.RootElement.TryGetProperty("tag_name", out var tagNameProperty)) { return tagNameProperty.GetString() ?? "0.0.0.0"; } return "0.0.0.0"; } catch { return "0.0.0.0"; } }
3. 正确调用异步方法
ViewModel加载时,需正确处理异步调用:
- 如果加载方法本身是异步的,直接用
await调用:
public async Task LoadViewModelAsync() { await CheckForUpdatesExecute(); // 其他初始化逻辑 }
- 如果加载方法是同步的,可使用
ContinueWith避免主线程阻塞:
public void LoadViewModel() { _ = CheckForUpdatesExecute().ContinueWith(task => { if (task.Exception != null) { // 处理异步方法抛出的异常 } }, TaskScheduler.FromCurrentSynchronizationContext()); }
内容的提问来源于stack exchange,提问作者Scott McAllister
相关产品推荐
相关产品推荐

