contextswitchdeadlock

在VS 2008中调试我的程序时,我遇到了以下错误:

CLR无法从COM上下文0x34fc1a0过渡到COM上下文0x34fc258 60秒。 拥有目标上下文/公寓的线程很可能是执行非抽空等待或处理非常长时间运行的操作而不抽取Windows消息。 这种情况通常会对性能产生负面影响,甚至可能导致应用程序变得无响应或内存使用量随时间不断累积。 为了避免这种情况

它似乎是死锁,即使代码只包含一个简单的C#计时器:请参阅下面的代码段:

private void RequestWork() { // The timer will be re-intialised if there are still no wating jobs in the database StopTimer(); // assign all the threads some work InitialiseTimer(); } ///  /// Initialise a timer with a timer interval configured from app.config. Enable the timer and /// register an appropriate event handler ///  private void InitialiseTimer() { if (m_Timer == null) { // look up the default backoff time from the config string backOffInt = ConfigurationSettings.AppSettings["BackOffInterval"]; int backoffInterval = 1000; m_Timer = new System.Timers.Timer(); // set the timer interval to 5 seconds m_Timer.Interval = backoffInterval; m_Timer.Elapsed += new ElapsedEventHandler(m_Timer_Elapsed); } m_Timer.Enabled = true; } private void StopTimer() { if (m_Timer != null) { m_Timer.Enabled = false; } } void m_Timer_Elapsed(object p_Sender, ElapsedEventArgs p_E) { RequestWork(); } 

据我所知,计时器应该运行,经过然后再次初始化,我看不出本地的死锁原因。

我知道如何关闭这个错误消息,但觉得这不是一个解决方案,而是它掩盖了问题。

如果你认为你肯定没有陷入僵局,你可以关闭它:

Visual Studio中的Debug-> Exceptions-> Managed Debug Assistants菜单,取消选中ContextSwitchDeadlock

这是一个无限循环。 您需要让应用程序每60秒至少抽一次消息,以防止发生此exception。 尝试偶尔调用System.Threading.Thread.CurrentThread.Join(10)。 还有其他一些电话可以让消息消失。

看来每次调用InitialiseTimer时都要添加一个新的事件处理程序。 这样,m_Timer_Elapsed将被添加多次调用。 您应该只添加一次事件处理程序。

如果您的应用程序在取消选中contextswitchdeadlock的框后仍然挂起或不响应。 在调用method或for循环之前放入以下行。

在C#中

 System.Windows.Forms.Application.DoEvents(); 

和VB.NET / VB / ASP.NET

 DoEvents() 

几个想法/问题:

1)代码片段看起来像你的间隔是每1秒(不是评论中提到的5)。 2)最大的问题是RequestWork()在做什么?

在不知道RequestWork()正在做什么的情况下,我们无法真正评论您为何看到ContextSwitchDeadlock。

关于这种方法需要思考的事情a)需要多长时间? b)是否访问GUI元素?

一些MSDN对Elapsed的评论:

如果将Timer与用户界面元素(如窗体或控件)一起使用,请将包含Timer的窗体或控件分配给SynchronizingObject属性,以便将事件封送到用户界面线程。

-和-

在ThreadPool线程上引发Elapsed事件。 如果Elapsed事件的处理持续时间超过Interval,则可能会在另一个ThreadPool线程上再次引发该事件。 因此,事件处理程序应该是可重入的。

我在想,因为你有1秒计时器,你可能想看看RequestWork中发生了什么,看看它有多长时间。