首页 > 解决方案 > Lambda 遇到 UnobservedTaskException - 无法访问已处置的对象

问题描述

我一直在 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)"
        ]
    }]
}

lambda 代码非常简单:它SNS messages使用Dapper.

我认为我async在 Fucntion 处理程序中的工作方式可能存在一些问题。有任何想法吗?

public class Function
{
    private static string _connectionString;

    public async Task<IEnumerable<InsertSnsResult>> FunctionHandler(SNSEvent @event, ILambdaContext context)
    {
        try
        {
            context.Logger.LogLine("Adding SNS Messages");
            _connectionString = _connectionString ?? await DecryptHelper.DecryptEnvironmentVariableAsync("ConnectionString").ConfigureAwait(false);
            var handler = new AddSnsMessageHandler(new SnsMessagesRepository(_connectionString, context.Logger));
            return await handler.AddSnsEvents(@event).ConfigureAwait(false);
        }
        catch (Exception e)
        {
            context.Logger.LogLine(e.Message);
            throw;
        }
        finally
        {
            context.Logger.LogLine("Finished SNS Adding Messages");
        }
    }
}

[编辑]

这里要清楚,这个异常不会被 try/catch 块捕获。如果是这样,它就不会是一个UnobservedTaskException. 这就是为什么我很难找到问题的根源。

这是存储库代码

public async Task<List<InsertSnsResult>> InsertSnsMessages(IEnumerable<SnsEvent> records)
{
    using (var connection = new SqlConnection(_connectionString))
    {
        await connection.OpenAsync().ConfigureAwait(false);

        var results = new List<InsertSnsResult>();
        foreach (var record in records)
        {
            try
            {
                await connection.ExecuteAsync(InsertEventCommand, record).ConfigureAwait(false);
                results.Add(new InsertSnsResult(record.CorrelationId, true));
            }
            catch (Exception ex)
            {
                _logger.LogLine($"InsertSns failed for {record.Id}. {ex.Message}");
                results.Add(new InsertSnsResult(record.CorrelationId, false));
            }
        }

        return results;
    }            
}

标签: c#async-awaitaws-lambdaamazon-cloudwatchobjectdisposedexception

解决方案


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

  • 你有一个异步任务
  • 该异步任务正在访问一个已经被释放的对象,可能是因为您的工作流中有一些竞争条件,异步工作流中的一个对象与需要它的工作流的另一部分无序释放。 这意味着这个工作流程中的某些东西被严重破坏了
  • 异步任务从不等待,要么与 await 异步,要么(不要这样做!)与 Result 或 Wait 同步。这意味着永远不会采用异常延续路径,并且任务在收集它时会注意到这一点。同样,如果您有一项从不等待结果的任务,那么您的工作流程中可能会出现严重问题。将这一事实与前一点的事实相结合:我们现在有两个证据相互支持,表明此工作流程中存在严重问题,并且它涉及一个未等待的任务,而该任务本应确保排序约束.
  • 因此,您在终结器线程上遇到异常,这真的很糟糕

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

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


推荐阅读