代码之家  ›  专栏  ›  技术社区  ›  BlueRaja - Danny Pflughoeft

CLR无法从COM上下文[…]转换60秒

  •  36
  • BlueRaja - Danny Pflughoeft  · 技术社区  · 14 年前

    我在以前工作的代码上发现了这个错误。我没有改密码。

    以下是完整的错误:

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

    下面是导致它的代码:

    var openFileDialog1 = new System.Windows.Forms.OpenFileDialog();
    openFileDialog1.DefaultExt = "mdb";
    openFileDialog1.Filter = "Management Database (manage.mdb)|manage.mdb";
    
    //Stalls indefinitely on the following line, then gives the CLR error
    //one minute later.  The dialog never opens.
    if(openFileDialog1.ShowDialog() == DialogResult.OK)
    {
        ....
    }
    

    是的,我确信对话框没有在后台打开,不,我没有任何显式的COM代码、非托管封送处理或多线程处理。

    我不知道为什么openfiledialog不打开-有什么想法吗?

    6 回复  |  直到 7 年前
        1
  •  12
  •   BlueRaja - Danny Pflughoeft    13 年前

    明白了-每次对话框打开时,它会自动将您带到最后一个查看的位置。如果该位置是一个不再存在的网络位置(例如,另一台计算机关闭),它将永远挂起。

    我的解决方法如下:

    string initialDirectory = ...; //Figure out an initial directory from somewhere
    openFileDialog1.InitialDirectory = !Directory.Exists(initialDirectory)
                                           ? Path.GetPathRoot(Environment.SystemDirectory)
                                           : initialDirectory;
    
        2
  •  11
  •   i_am_jorf    11 年前

    因此,它抱怨的是COM上下文,即使您没有显式地使用COM,因为在所有可爱的C代码下面打开一个本机shell对话框,shell确实使用COM。

    这条消息告诉你的是,无论它试图做什么,它都是在ui线程上做的,而不是以一种好的方式,这似乎需要很长时间。很明显,任何错误本身都不是你的错,所以你可以忽略它给你的大部分建议。

    要尝试的事情:

    1. 首先我会尝试 AaronLS 建议,简化 openFileDialog 尽可能多。试着不做任何设置;只要创建一个新的人并打电话给 ShowDialog() . 如果这解决了问题,那么你就给了它一个格式错误的参数,我们可以继续讨论它的含义。然而,如果它不起作用,那就意味着壳牌公司出了问题。

    2. 可能发生这种情况的一个可能原因是,您安装了一个shell扩展,它正在做一些不好的事情。你最好做的就是 break-in (ctrl+break in Visual Studio 我认为,或者 debug->break all 在菜单栏上)给我们拿完整的一堆。当对话框出现时,我们应该能够通过查看堆栈上的人来识别罪魁祸首。

        3
  •  9
  •   Roman O    7 年前

    解决此问题的一个方法是转到Visual Studio中的“调试”->“异常”->“托管调试助手”菜单,然后取消选中ContextSwitchDeadlock

    http://blog.wpfwonderland.com/2007/08/16/clr-has-been-unable-to-transition-from-com-context-for-60-seconds/

    更新: 请不要轻视,如果你公平地认为,这种变通方法是个糟糕的主意。很多人尝试了许多列为答案的解决方案,但我的变通方法是唯一帮助他们的方法。这就是为什么答案仍然是肯定的。

        4
  •  6
  •   Ghasem    9 年前

    我在处理大型数据库时遇到了这个问题,它使用户界面冻结了很长一段时间。所以我把密码放在 BackgroundWorker 现在问题解决了。多亏了“我是乔夫”

    这个信息告诉你的是无论它想做什么, 这是在ui线程上做的,但不是很好,而且看起来 要花很长时间。

    private void btnConvert_Click(object sender, EventArgs e)
    {
      Cursor = Cursors.WaitCursor;
      bgwConvert.RunWorkerAsync();
    }
    
    private void bgwConvert_DoWork(object sender, DoWorkEventArgs e)
    {
      //My taking-lots-of-time codes
    }
    
    private void bgwConvert_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
      Cursor = Cursors.Default;
      MessageBox.Show("Done");
    }
    
        5
  •  2
  •   yoel halb    9 年前

    我也遇到了这个问题,我通过将我的.NET框架更改为最新的.NET框架(在我的例子中是.NET框架4.5,从项目属性 窗口->调试->.NET框架 ,并将CPU类型从 x86 任何CPU (在项目属性中 窗口->生成->平台目标 )

        6
  •  2
  •   Mohamed Nagieb    7 年前

    我刚才也遇到了同样的问题,我的解决方法很简单: 清洗溶液并重建!

    我正在使用Visual Studio 2015。

    希望这个能有帮助。