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

Blu*_*eft 38 .net c#

我在以前的代码上遇到此错误.我没有改变代码.

这是完整的错误:

CLR无法从COM上下文0x3322d98过渡到COM上下文0x3322f08达60秒.拥有目标上下文/公寓的线程很可能是在非抽空等待或处理非常长时间运行的操作而不抽取Windows消息.这种情况通常会对性能产生负面影响,甚至可能导致应用程序变得无响应或内存使用量随时间不断累积.为了避免这个问题,所有单线程单元(STA)线程都应该使用抽取等待原语(例如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)
{
    ....
}
Run Code Online (Sandbox Code Playgroud)

是的,我确定对话框没有在后台打开,不,我没有任何明确的COM代码或非托管编组或多线程.

我不知道为什么OpenFileDialog不会打开 - 任何想法?

Blu*_*eft 14

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

我的解决方法如下所示:

string initialDirectory = ...; //Figure out an initial directory from somewhere
openFileDialog1.InitialDirectory = !Directory.Exists(initialDirectory)
                                       ? Path.GetPathRoot(Environment.SystemDirectory)
                                       : initialDirectory;
Run Code Online (Sandbox Code Playgroud)


i_a*_*orf 12

所以,它抱怨COM上下文,即使你没有明确使用COM,因为在所有可爱的c#代码下面打开一个本机shell对话框,而shell确实使用了COM.

这条消息告诉你的是,无论它想做什么,它都是在UI线程上进行而不是以一种很好的方式进行,这似乎需要很长时间.显然,任何错误都不是你自己的错,所以你可以忽略它给你的大部分建议.

要尝试的事情:

  1. 首先,我会尝试尽可能地AaronLS简化您的工作openFileDialog.尽量不设置任何东西; 只是创建一个新人并打电话ShowDialog().如果这解决了问题,那么你刚刚给出了错误的参数,我们可以谈谈它的含义.但是,如果它不起作用,那就意味着贝壳土地上出了问题.

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


Rom*_*n O 11

解决此问题的一个方法是转到Visual Studio中的Debug - > Exceptions - > Managed Debug Assistants菜单并取消选中ContextSwitchDeadlock

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

更新:如果您认真考虑,请不要贬低,这种解决方法很糟糕.许多人在这里尝试了许多解决方案作为答案,但我的解决方法是唯一帮助他们的方法.这就是为什么答案仍然有积极的分数.

  • 隐藏异常并不意味着它已经消失了! (30认同)
  • 虽然我通常会同意吞下异常是一种不好的做法,但我刚刚遇到这个问题试图解决这个问题.该解决方案适合我的需求.不要以为每个人都在构建200万行代码业务应用程序 - 有时在我的情况下,我只是编写一个小型数据迁移工具,我不关心我的UI是否正在更新.这个解决方案允许我的程序不受阻碍地运行,现在我可以回到床上等待早上完成它. (4认同)
  • 这是一个糟透了的想法. (3认同)
  • 丹,你能解释一下,为什么这很糟糕? (2认同)

Ale*_*lig 7

我在使用大型数据库时遇到了这个问题,它使用户界面长时间冻结.所以我把代码放进BackgroundWorker去,现在问题就消失了.感谢@i_am_jorf

这条消息告诉你的是,无论它想做什么,它都是在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");
}
Run Code Online (Sandbox Code Playgroud)