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

为何Prise插件中TaskCanceledException无法捕获,其他异常却可以?

Prise插件框架中TaskCanceledException无法被上层捕获的问题与解决办法

问题背景

我在使用Prise Plugin Framework和MailKit SMTP Client时遇到异常处理异常:当调用ConnectAsync异步超时抛出TaskCanceledException时,该异常在调用方被捕获并记录日志后重新抛出,但无法被Prise插件Execute方法的上层catch块捕获,直接导致应用崩溃;而其他类型的异常则能正常被上层捕获,不会引发崩溃。

相关代码示例

初始异常捕获逻辑

try
{
    await _smtpClient.ConnectAsync(sendEmail.Host, sendEmail.Port);
    // 其他业务代码
}
catch
{
    // 日志记录逻辑
    throw;
}

这段代码由插件通过return await service.ExecuteAsync(parameters, context);调用,原本预期异常会抛到父级处理,但未生效。

插件类及上层调用代码

[Plugin(PluginType = typeof(IPlugin))]
[PluginDescription(Description = "Email plugin.")]
public class Email : BasePlugin<EmailInputModel>
{
    [field: PluginService(ProvidedBy = ProvidedBy.Host, ServiceType = typeof(IServiceProvider))]
    private IServiceProvider ServiceProvider { get; set; }

    [PluginActivated]
    public void OnActivated()
    {
        InitializeServices(ServiceProvider);
    }

    protected override async Task<PluginExecutionResult> ExecutePluginAsync(
        EmailInputModel parameters,
        PluginExecutionContext context,
        IServiceProvider provider)
    {
        IEmailPluginService service = provider.GetRequiredService<IEmailPluginService>();
        return await service.ExecuteAsync(parameters, context);
    }
}

// 调用插件Execute方法的上层逻辑
public async Task<PluginExecutionResult> ExecuteAsync(string parameters, PluginExecutionContext context)
{
    try
    {
        var pluginParameters = JsonConvert.DeserializeObject<TInput>(parameters);

        using var scope = _serviceProvider.CreateScope();
        return await ExecutePluginAsync(pluginParameters, context, scope.ServiceProvider);
    }
    catch (Exception exception)
    {
        // 预期在此捕获异常,但实际未触发
        throw;
    }
}

解决办法

我通过在Connect超时后专门捕获OperationCanceledException(TaskCanceledException是它的子类),并在catch块中抛出一个自定义异常,解决了这个问题。调整后的核心代码如下:

try
{
    await _smtpClient.ConnectAsync(sendEmail.Host, sendEmail.Port);
    // 其他业务代码
}
catch (OperationCanceledException)
{
    // 日志记录
    throw new CustomEmailTimeoutException("SMTP连接超时"); // 自定义异常类,需提前定义
}
catch
{
    // 其他异常处理及日志
    throw;
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.16 10:12:09