【问题标题】:Why an exception in ThreadPool.QueueUserWorkItem action does not crash an application when it should?为什么 ThreadPool.QueueUserWorkItem 操作中的异常不会导致应用程序崩溃?
【发布时间】:2022-01-26 23:11:17
【问题描述】:

我有问题。 ThreadPool.QueueUserWorkItem 中的异常不会使应用程序崩溃,但我希望它崩溃,而且我通常知道它会崩溃。我的情况有所不同。我的ThreadPool.QueueUserWorkItem 被包裹成这样的等待者

public struct YieldThreadPoolAwaiter : INotifyCompletion
{
    public void OnCompleted(Action continuation)
    {
        if (continuation == null)
        {
            throw new ArgumentNullException(nameof(continuation));
        }
        ThreadPool.QueueUserWorkItem(RunAction, continuation);
    }

    public void GetResult() { }

    private static void RunAction(object state)
    {
        ((Action)state)();
    }

    public bool IsCompleted
    {
        get { return false; }
    }
}

对我来说,它看起来与调用 ThreadPool.QueueUserWorkItem 相同,但在这里我这样做时会间接调用它:

await ThreadPoolEx.Yield();

我看到执行是在ThreadPool.QueueUserWorkItem 内部进行的,我知道那里抛出了一个异常,但异常不知何故被悄悄吞下,应用程序没有崩溃。

问题是 - 为什么?在这种情况下应用程序不会崩溃,以及如何改回这种行为并使其崩溃?

【问题讨论】:

  • 显示更多代码 - 例如ThreadPoolEx.Yield 实现以及引发异常的位置
  • 您使用的是什么版本和风格的 .net?
  • 我无法复制它。我用一个抛出的动作调用OnCompleted,我得到了未处理的异常,如预期的那样。 Here 是我的复制尝试。

标签: c# .net exception threadpool


【解决方案1】:

我怀疑您是从async Task 方法中调用await ThreadPoolEx.Yield();,例如this fiddle

在这种情况下,传递给OnCompleted 的延续不仅仅是您的代码;它是async 状态机生成的代码的适当部分。如果该代码在 async Task 方法中,则生成的状态机代码的一部分会故意捕获异常并将它们放在返回的任务中。

总结:行为符合预期。如果您希望 async 方法中的异常使应用程序崩溃,请使用 async void 而不是 async Task

【讨论】:

    猜你喜欢
    • 2014-11-25
    • 2021-12-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-05-26
    • 2011-03-21
    • 2019-09-08
    • 1970-01-01
    相关资源
    最近更新 更多