You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.13 23:50:24