【问题标题】:Why does invoking a non-existing dictionary key hang my program?为什么调用不存在的字典键会挂起我的程序?
【发布时间】:2022-12-12 20:48:40
【问题描述】:

我有一个字典,其中字符串作为键,异步函数作为值。它是这样定义的:

_messageMap = new Dictionary<string, Func<UpgradeTask, Task>>
{
    { "Upgrade1", Upgrade1 }
};

函数如下所示:

private async Task Upgrade1(UpgradeTask upgradePayload)
{
    await _databaseFunctions.DoUpgrade("Upgrade1", upgradePayload.UpgradeId);
}

这一切都包含在一个类中,该类具有一个执行方法,该方法将通过它获取的字符串调用适当的函数。它本质上是一种回调机制,用于将来发生事件时的回调机制。执行看起来像这样:

public async Task Execute(FutureEvent futureEvent)
{
    var payLoad = JsonSerializer.Deserialize<UpgradeTask>(futureEvent.Message);
    await _messageMap[payLoad.UpgradeId].Invoke(payLoad);
}

然而,如果有效载荷曾经有一个不在字典中的 UpgradeId,这似乎会无限期地挂起。

我期望发生的是,如果 UpgradeId 存在于字典中,它将调用该函数。实际上在那种情况下效果很好。但是,如果 UpgradeId 位于字典中不存在的有效负载中,似乎会发生什么,它会无限期挂起。就好像在等待永远不会发生的事情。我认为它会跳过它,甚至可能会出错。但它只是默默地失败并永远挂起。这是一个问题,因为它实际上并没有使应用程序的其余部分崩溃。其他一切似乎都工作正常,但如果字典中不存在任何一个事件,则不会处理任何回调。

为什么会这样?我知道我可以事先检查它是否存在于字典中。但我仍然很困惑为什么 await 在那一刻永远挂起。我想了解我做错了什么。

【问题讨论】:

  • 如果键不在字典中,则抛出异常(KeyNotFoundException)。现在它取决于你最终如何调用 Execute 方法,如果你总是在调用链中 await 或者你是否(以及如何)在某个地方处理异常。
  • 它没有。由于当您提供不存在的密钥时字典会抛出 KeyNotFoundException,因此不会发生任何调用。您需要找出该异常是如何/在何处被吞噬的,然后弄清楚在那之后发生了什么。也许这是在某个更大的框架内,该框架不断尝试一遍又一遍地处理相同的有效负载。不可能从这里的碎片说
  • 我猜从 Execute 返回的任务将 IsFaulted 设置为 true

标签: c# .net dictionary async-await


【解决方案1】:

看看这个问题,它很好地解释了你的问题。

Why does this async action hang when I try and access the Result property of my Task?

为你的 _databaseFunctions 实现一个接口,你可以在其中定义一个任务,这也可以省去检查条目是否存在于字典中的麻烦

【讨论】:

    猜你喜欢
    • 2014-04-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-11-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多