当前位置: 首页 > 知识库问答 >
问题:

停止异步lambda传播向上调用堆栈的异常

洪逸清
2023-03-14

下面的代码有一个TaskMonitor类,它是Stephen Cleary的NotifyTask类的修改版本。Worker类使用TaskMonitor类异步运行Worker.CheckStatus。

Worker.CheckStatus经常会引发异常(例如数据库连接问题)。我希望TaskMonitor.Monitor阻止异常到达Program.Main并通过Exception和InnerException属性公开它。TaskMonitor.Monitor中的catch块被命中,但没有像预期的那样吞下异常;异常会传递给program.main并使应用程序崩溃。如何停止TaskMonitor.Monitor中的异常?

public sealed class TaskMonitor {
    // Based on Stephen Cleary's NotifyTaskCompletion:
    // https://github.com/StephenCleary/Mvvm/blob/master/future/Nito.Mvvm.Async/NotifyTask.cs

    public TaskMonitor(Task task = null) {
        Task = task;
    }

    public AggregateException Exception {
        get {
            return Task?.Exception;
        }
    }

    public Exception InnerException {
        get {
            return Exception?.InnerException;
        }
    }

    public bool IsCompleted {
        get {
            return Task != null && Task.IsCompleted;
        }
    }

    public bool IsRunning {
        get {
            return Task != null && !Task.IsCompleted;
        }
    }

    private async Task Monitor(Task task) {
        try {
            if(task != null) {
                await task;
            }
        }
        catch {
            // Drop exceptions
        }
        finally {
            // do other stuff here like raise PropertyChanged
        }
    }

    private Task _task;

    public Task Task {
        get => _task;
        set {
            if(Task != value) {
                _task = value;
                _ = Monitor(Task);
            }
        }
    }
}

public class Worker {
    public Worker() {
        CheckStatusMonitor = new TaskMonitor();
    }

    public void CheckStatus() {
        if(!CheckStatusMonitor.IsRunning) {
            CheckStatusMonitor.Task = Task.Run(async () => {
                var newStatus = WorkerStatus.Unknown;
                try {
                    // Force a database connection failure
                    var cn = new SqlConnection();
                    await cn.OpenAsync();

                    newStatus = WorkerStatus.Good;
                }
                catch(Exception ex) {
                    newStatus = WorkerStatus.Error;
                    throw ex;
                }
                finally {
                    Status = newStatus;
                }
            });
        }
    }

    public TaskMonitor CheckStatusMonitor { get; private set; }

    public WorkerStatus Status { get; private set; }
}

public enum WorkerStatus {
    Unknown,
    Error,
    Good,
}

class Program {
    public static async Task Main() {
        var worker = new Worker();
        worker.CheckStatus();
        await worker.CheckStatusMonitor.Task;
        Debug.WriteLine(worker.CheckStatusMonitor.ErrorMessage);
    }
}

共有1个答案

麻鸿熙
2023-03-14

TaskMonitor.Monitor中的catch块被命中,但没有像预期的那样吞下异常;异常会传递给program.main并使应用程序崩溃。如何停止TaskMonitor.Monitor中的异常?

main中,您的代码正在执行Await Worker.CheckStatusMonitor.task;TaskMonitor.task返回的任务是从Worker.CheckStatus返回的task.Run任务,而不是从TaskMonitor.Monitor返回的任务。

如果要忽略异常,则需要await正确的任务:

public Task Task {
  get => _task;
  set {
    _task = Monitor(value);
  }
}

请注意,if(Task!=value)已被删除,因为任务正在被替换,这显然是行不通的。

 类似资料:
  • 我有一个由S3推送事件触发的AWS Lambda。lambda将调用一个API,这将触发一个长时间运行的进程。我认识到我可以配置S3异步调用lambda函数,因此S3不会等待响应,但我很想知道我是否可以配置lambda异步调用我的API。我不希望lambda在过程完成时等待几分钟。有人能给我指出一些概述这个过程的留档吗?提前谢谢。

  • 我有一个用c#编写的AWS lambda函数。此函数负责调用5-6个API调用(Post请求)。 所有这些API调用都是相互独立的。 我不关心这些API调用的响应。 即使我不关心后续响应,每个API调用也需要大约5秒才能完成。 问题:我希望lambda函数在一秒钟内执行并响应。如何异步进行API调用,使lambda函数能够在我的时间限制内完成所有这些操作,而不必等待API调用的响应?理想情况下,我

  • 问题内容: 我需要从另一个lambda异步调用aws lambda。我有一个用于同步呼叫的工作代码。 但就我而言,“ testLambda”是一个耗时的函数。因为我需要在调用“ testLambda”函数后退出。然后像这样更新代码 它正确返回消息。但是我的’testLambda’函数没有被调用(测试lambda不会生成云监视日志)。与此代码相关的问题是什么。 问题答案: 根据Lambda invo

  • 问题内容: 更新 :Intellij IDEA的最新版本完全实现了我想要的功能。问题是如何在IDE外部实现此功能(以便我可以将异步堆栈跟踪信息转储到日志文件中),理想情况下无需使用检测代理。 自从我将应用程序从同步模型转换为异步模型以来,调试故障一直遇到问题。 当我使用同步API时,我总是在异常stacktraces中找到我的类,因此我知道从哪里开始寻找问题。使用异步API,我得到的堆栈跟踪既不引

  • 实现异步启动 下面是一个示例: public class MyVerticle extends AbstractVerticle { public void start(Future<Void> startFuture) { // Now deploy some other verticle: vertx.deployVerticle("com.foo.OtherVerticl

  • 我有一个聊天应用程序,当我在输入消息后单击按钮时,消息会发布到我的DynamoDB表中。该应用程序应该发布一次消息,但不知何故发布了两次。 管道如下: 客户端单击“发送”按钮-- 在SO的帮助下,我已经将问题隔离到我的Google Cloud函数异步调用Lambda,该函数将Lambda排队两次。 使用async,请求在实际执行之前排队。所以,如果您调用它一次,AWS将检查是否已经有一个正在执行,