为了账号安全,请及时绑定邮箱和手机立即绑定

Lambda 遇到 UnobservedTaskException - 无法访问已处置的对象

Lambda 遇到 UnobservedTaskException - 无法访问已处置的对象

C#
函数式编程 2022-01-09 16:43:43
我一直在 AWS Lambda 的 CloudWatch 日志中注意到此异常。一切似乎都得到了处理,所以我认为这是在 Lambda 完成执行后创建的 AWS 代码中的异常(与我编写的代码相反)。由于在功能上它有效,我一直忽略它,但我担心可能存在我没有注意到的问题。Lambda 通过 'TaskScheduler.UnobservedTaskException' 事件遇到了 UnobservedTaskException:{    "errorType": "AggregateException",    "errorMessage": "A Task's exception(s) were not observed either by Waiting on the Task or accessing its Exception property. As a result, the unobserved exception was rethrown by the finalizer thread. (Cannot access a disposed object.\nObject name: 'System.Net.Sockets.UdpClient'.)",    "cause": {        "errorType": "ObjectDisposedException",        "errorMessage": "Cannot access a disposed object.\nObject name: 'System.Net.Sockets.UdpClient'.",        "stackTrace": [            "at System.Net.Sockets.UdpClient.EndReceive(IAsyncResult asyncResult, IPEndPoint& remoteEP)",            "at System.Net.Sockets.UdpClient.<>c.<ReceiveAsync>b__56_1(IAsyncResult asyncResult)",            "at System.Threading.Tasks.TaskFactory`1.FromAsyncCoreLogic(IAsyncResult iar, Func`2 endFunction, Action`1 endAction, Task`1 promise, Boolean requiresSynchronization)"        ]    },    "causes": [ {        "errorType": "ObjectDisposedException",        "errorMessage": "Cannot access a disposed object.\nObject name: 'System.Net.Sockets.UdpClient'.",        "stackTrace": [            "at System.Net.Sockets.UdpClient.EndReceive(IAsyncResult asyncResult, IPEndPoint& remoteEP)",            "at System.Net.Sockets.UdpClient.<>c.<ReceiveAsync>b__56_1(IAsyncResult asyncResult)",            "at System.Threading.Tasks.TaskFactory`1.FromAsyncCoreLogic(IAsyncResult iar, Func`2 endFunction, Action`1 endAction, Task`1 promise, Boolean requiresSynchronization)"        ]    }]}
查看完整描述

2 回答

?
不负相思意

TA贡献1777条经验 获得超10个赞

日志消息很简单,并解释了正在发生的事情:

  • 你有一个异步任务

  • 该异步任务正在访问一个已经被释放的对象,可能是因为您的工作流中有一些竞争条件,异步工作流中的一个对象与需要它的工作流的另一部分无序释放。 这意味着这个工作流程中的某些东西被严重破坏了

  • 异步任务从不等待,要么与 await 异步,要么(不要这样做!)与 Result 或 Wait 同步。这意味着永远不会采用异常延续路径,并且任务在收集它时会注意到这一点。同样,如果您有一项从不等待结果的任务,那么您的工作流程中可能会出现严重问题。将这一事实与前一点的事实相结合:我们现在有两个证据相互支持,表明此工作流程中存在严重问题,并且它涉及一个未等待的任务,而该任务本应确保排序约束.

  • 因此,您在终结器线程上遇到异常,这真的很糟糕

由于它在功能上有效,我一直忽略它

我曾经听说,当一家工厂着火并被烧毁时,平均有七种不同的安全系统被人们忽视或禁用。摆脱这种认为它有效的习惯,所以它必须是安全的。也许没什么,但我会认为这些消息表明存在严重问题,直到我有其他证据。


查看完整回答
反对 回复 2022-01-09
?
元芳怎么了

TA贡献1798条经验 获得超7个赞

我也遇到了一个有 3rd 方库导致错误的地方。我想在 CloudWatch 之外记录它。为了防止 Lambda 记录这些,我能够做一些邪恶的反射来重置事件处理程序。


这是您自己执行此操作的代码。请注意这是邪恶的代码。它很脆弱,并且会在 CLR 中的代码更改或即使编译器进行优化(最近发生的)时中断。但是,这是我能找到退出 Lambda 提供的此功能的唯一方法


private void ReplaceLambdaDefaultUnobservedTaskException()

{

    try

    {

        var bindingFlags = BindingFlags.NonPublic | BindingFlags.Static;

        Type type = typeof(TaskScheduler);


        var field = type.GetField("_unobservedTaskException", bindingFlags);


        if (field == null)

        {

            field = type.GetField("UnobservedTaskException", bindingFlags);

        }


        var handler = new EventHandler<UnobservedTaskExceptionEventArgs>(TaskSchedulerOnUnobservedTaskException);

        field.SetValue(null, handler);

    }

    catch (Exception ex)

    {

        logger.Warning(ex, "Unable to do evil reflection.");

    }


    TaskScheduler.UnobservedTaskException += TaskSchedulerOnUnobservedTaskException;

}


private void TaskSchedulerOnUnobservedTaskException(object sender, UnobservedTaskExceptionEventArgs e)

{

    e.SetObserved();

    logger.Error(e.Exception, "Lambda threw an UnobservedTaskException");

}


查看完整回答
反对 回复 2022-01-09
  • 2 回答
  • 0 关注
  • 233 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信