【问题标题】:ContextSwitchDeadlock Was Detected error in C#在 C# 中检测到 ContextSwitchDeadlock 错误
【发布时间】:2011-02-17 08:49:21
【问题描述】:

我正在运行一个 C# 应用程序,在运行时出现以下错误:

CLR 在 60 秒内无法从 COM 上下文 0x20e480 转换到 COM 上下文 0x20e5f0。拥有目标上下文/单元的线程很可能要么进行非泵送等待,要么处理非常长时间运行的操作而不泵送 Windows 消息。这种情况通常会对性能产生负面影响,甚至可能导致应用程序变得无响应或内存使用量随着时间的推移不断累积。为避免此问题,所有单线程单元 (STA) 线程都应使用泵送等待原语(例如 CoWaitForMultipleHandles)并在长时间运行的操作期间定期泵送消息。

谁能帮我解决这里的问题?

非常感谢。

【问题讨论】:

    标签: c# multithreading


    【解决方案1】:

    假设您使用的是 Visual Studio,您可以在当前项目中单击 Ctrl+Alt+E,然后将显示异常窗口并选择 托管调试助手,您应该取消选中“ContextSwitchDeadlock”选项。然后构建一个当前项目。

    【讨论】:

    • 它只是跳过了异常,但问题是关于问题或解决方案的解释......无法解决。
    【解决方案2】:

    我多次遇到此错误,我将其追溯到DataGridViewRow 中的迭代,其中我将复选框值设置为 true。由于我在调试模式下运行,我可以选择继续,所以我能够做到这一点。

    我希望这对某人有所帮助。

    【讨论】:

      【解决方案3】:

      当我试图弄清楚为什么我的 OracleDataReader 抛出异常时,我遇到了这个问题。我认为这是因为它被分配了null,因为异常与“null”参数有关。所以我做了:

      while (dr.Read())
      {
          while (dr != null)  // <-- added this line
          {
            ...
      

      原来dr 永远不会为空,因此循环一直持续到此消息到达,然后再循环一些,因为您可以单击“继续”以使其继续运行,直到内存不足(不要这样做 - 而是单击“确定”)。故事的寓意是,寻找内存泄漏,即数据从数据库流式传输到内存中循环到无穷大。该错误实际上是试图警告您一个糟糕的情况。最好听听。

      【讨论】:

        【解决方案4】:

        要查找哪个操作阻止了上下文切换并导致显示contextSwitchDeadlock MDA,您可以使用以下步骤。请注意,我指的是 Visual Studio 2012。

        1. 重现错误。这可能需要反复试验。
        2. 在显示的托管调试助手中单击“确定”而不是“继续”。
        3. 通过右键单击工具栏停靠区域并选择“调试位置”来确保“调试位置”工具栏处于活动状态。如果它处于活动状态,您应该会在工具栏中看到一个标有“线程”的下拉列表。
        4. “线程”下拉列表中的选定项应该是主线程以外的线程,因为它将是抱怨主线程占用所有注意力的后台线程。在下拉列表中选择主线程。
        5. 您现在应该会在代码编辑器中看到阻止上下文切换的代码。

        假设您决定不将资源密集型操作移出主线程 - 在此之前先查看其他一些答案和 cmets - 您可以使用以下选项来禁用托管调试助手。

        在 Visual Studio 调试器中

        1. 您可以直接在 MDA 对话框中禁用 MDA 通过取消选中“Break when this”发生错误时显示 异常类型被抛出”。
        2. 使用来自MSDN 的以下说明使用“异常设置”对话框。

        ...在“调试”菜单上,单击“例外”。 (如果“调试”菜单不包含“异常”命令,请单击“工具”菜单上的“自定义”以添加它。)在“异常”对话框中,展开“托管调试助手”列表,然后清除单个 MDA 的“抛出”复选框。

        在 Visual Studio 调试器之外

        1. Registry Key(机器范围,所有 MDA 受影响)
        2. Environment Variable(机器范围,可以指定 MDA)
        3. Application Configuration Settings(应用范围,MDA可以指定)

        注意:前两个选项之一必须设置为 1,第三个选项才会生效。

        就我而言,问题是在控制台应用程序的实体框架中调用ObjectContext.SaveChanges()。将MTAThreadAttribute 应用于Main() 方法不再引发ContextSwitchDeadlock 异常。不幸的是,我不确定此更改的全部影响。

        【讨论】:

        • 赞成明确解释如何找到阻止进程的代码。
        【解决方案5】:

        您程序的主线程已经忙于执行代码一分钟了。它没有处理其正常职责,而是抽出消息循环。当您在工作线程中使用 COM 服务器时,这是非法的:在您的主线程再次空闲之前,无法调度对其方法的调用。

        它应该很容易看到,你的 UI 应该像门钉一样死掉。 Windows 应该已经用显示“无响应”的幽灵替换了您的主窗口。关闭窗口不起作用,没有点击事件有任何影响。

        无论你的主线程在做什么,都应该由工作线程来完成。 BackgroundWorker 类对此很有用,您会在 MSDN Library 文章中找到许多使用帮助。如果您不知道主线程在做什么,请使用 Debug + Break All、Debug + Windows + Threads。

        还有一个可能的原因:如果您使用的是 VS2005 的 RTM 版本,请务必安装 Service Pack 1。

        【讨论】:

        • +1 用于解释这样的工作项应该移动到辅助线程,从而解决如何避免此错误(而不仅仅是产生错误的原因)。
        • 有趣的是,我看到其他一些内部构建的应用程序挂起的时间比我的要长得多,但我遇到了这个错误消息,嗯。
        • MSDN 文档:contextSwitchDeadlock MDA msdn.microsoft.com/en-us/library/ms172233%28v=vs.110%29.aspx
        • 感谢您的详细解释我使用的解决方法是异步函数,现在非常有意义。因此,据我所知,为长时间运行的操作管理一个新线程非常重要,尤其是在使用 COM 时。
        【解决方案6】:

        在某些情况下:
        调试 -> 异常 -> 托管调试助手
        并取消选中 ContextSwitchDeadlock 项。

        【讨论】:

        • 是的,但是当您正在编写一次性测试并且这会妨碍您时,能够禁用它真是太好了。
        • 没有。错误的。这不是问题的解决方案。
        • 你必须像工程师而不是科学家一样思考!!
        • @Ehsan Ershadi,一位优秀的工程师会预见并解决问题,而不是将其推到地毯下!
        • 哈哈。如果您不想看到错误,您可以简单地查看显示器以外的其他地方。这与您的“解决方案”相同。这不是一个解决方案。这只是忽略!
        【解决方案7】:

        只需从 Visual Studio 2005 窗口中的 Debug 菜单中选择 Exceptions,将弹出 Edxception 对话框,选择 Managed Debugging Assistants Exception Node,然后选择 ContextSwitchDeadlock 并从 Thrown 列中删除选择。这将阻止 vs 抛出 ContextSwitchDeadlock 异常。

        希望这会有所帮助..

        【讨论】:

        • 你的胳膊着火了。只需用刀子切断向大脑传递疼痛的神经。这会阻止你注意到你的手臂着火了。
        • 无论如何,这是一种暂时解决问题的方法。要彻底解决这个问题,需要一些时间重新考虑应用程序的设计。
        【解决方案8】:

        此消息表明您的某些代码正在尝试切换线程,并且目标线程正忙。例如,后台线程试图向 UI 线程发送调用以更新 UI,而 UI 正在运行一段时间的紧密循环。

        要真正弄清楚发生了什么,您需要进入调试器并查看所有线程以及它们在做什么。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2014-05-31
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多