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

C#中如何处理await Task返回null引发的异常?

问题分析与解决方案

根本原因

你遇到的StatusCode="Cancelled"异常,并非await处理null导致,而是gRPC Blazor WebView的协议限制:gRPC服务方法返回null时,会被判定为"未返回有效消息",进而触发取消状态的异常。

可行解决方案

方案1:用自定义结果对象包装返回值

创建包含状态标记的结果类,明确区分"找到数据"和"未找到数据"的场景,避免直接返回null:

// 定义结果包装类
public class DatabaseRegistryResult
{
    public bool IsFound { get; set; }
    public DatabaseRegistry? Registry { get; set; }
}

// 修改GetByName方法
public async Task<DatabaseRegistryResult> GetByName(string datasetName) 
{
    try
    {
        var entities = await _repository.GetAllAsync();
        var matchedRegistry = entities.FirstOrDefault(e => e.Name == datasetName);
        
        return new DatabaseRegistryResult
        {
            IsFound = matchedRegistry != null,
            Registry = matchedRegistry
        };
    }
    catch (Exception ex)
    {
        Console.WriteLine($"Error: {ex.Message}");
        throw new RpcException(new Status(StatusCode.Internal, "An error occurred while retrieving the database."));
    }
}

// 调用方逻辑
var queryResult = await appEngine.DatabaseRegistryService.GetByName(result.FileName);
if (queryResult.IsFound)
{
    // 处理找到数据的逻辑
    var curDbService = queryResult.Registry;
}
else
{
    // 处理未找到数据的逻辑
}

方案2:用Nullable引用类型(C# 8+)

如果项目已启用Nullable引用类型(在csproj中设置<Nullable>enable</Nullable>),可直接返回可空的DatabaseRegistry?,同时确保gRPC服务配置允许返回可空类型:

// 修改GetByName方法
public async Task<DatabaseRegistry?> GetByName(string datasetName) 
{
    try
    {
        var entities = await _repository.GetAllAsync();
        // 直接返回FirstOrDefault结果,无需额外包装Task.FromResult
        return entities.FirstOrDefault(e => e.Name == datasetName);
    }
    catch (Exception ex)
    {
        Console.WriteLine($"Error: {ex.Message}");
        throw new RpcException(new Status(StatusCode.Internal, "An error occurred while retrieving the database."));
    }
}

// 调用方逻辑保持不变
var curDbService = await appEngine.DatabaseRegistryService.GetByName(result.FileName);
if (curDbService != null)
{
    // 处理找到数据的逻辑
}
else
{
    // 处理未找到数据的逻辑
}

方案3:用异常区分"未找到"场景

如果业务允许将"未找到"视为异常场景,可抛出NotFound状态的gRPC异常,在调用方捕获后处理:

// 修改GetByName方法
public async Task<DatabaseRegistry> GetByName(string datasetName) 
{
    try
    {
        var entities = await _repository.GetAllAsync();
        var matchedRegistry = entities.FirstOrDefault(e => e.Name == datasetName);
        
        if (matchedRegistry == null)
        {
            throw new RpcException(new Status(StatusCode.NotFound, $"Registry '{datasetName}' not found."));
        }
        
        return matchedRegistry;
    }
    catch (RpcException)
    {
        // 重新抛出gRPC异常,不做额外包裹
        throw;
    }
    catch (Exception ex)
    {
        Console.WriteLine($"Error: {ex.Message}");
        throw new RpcException(new Status(StatusCode.Internal, "An error occurred while retrieving the database."));
    }
}

// 调用方逻辑
try
{
    var curDbService = await appEngine.DatabaseRegistryService.GetByName(result.FileName);
    // 处理找到数据的逻辑
}
catch (RpcException ex) when (ex.StatusCode == StatusCode.NotFound)
{
    // 处理未找到数据的逻辑
}
catch (RpcException ex) when (ex.StatusCode == StatusCode.Internal)
{
    // 处理内部错误逻辑
}

内容的提问来源于stack exchange,提问作者Penny

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.18 00:45:15