上下文切换死锁
在 VS 2008 中调试我的程序时,我遇到了以下错误:
CLR 在 60 秒内无法从 COM 上下文 0x34fc1a0 转换到 COM 上下文 0x34fc258。 拥有目标上下文/单元的线程很可能执行非泵送等待或处理非常长时间运行的操作而不泵送 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();
}
/// <summary>
/// Initialise a timer with a timer interval configured from app.config. Enable the timer and
/// register an appropriate event handler
/// </summary>
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();
}
据我所知,计时器应该运行、流逝,然后再次初始化,我看不出死锁的本地原因。
我知道如何关闭此错误消息,但觉得这不是解决方案,而是掩盖了问题。
Whilst debugging my program in VS 2008 I have come across the following error:
The CLR has been unable to transition from COM context 0x34fc1a0 to COM context 0x34fc258 for 60 seconds. The thread that owns the destination context/apartment is most likely either doing a non pumping wait or processing a very long running operation without pumping Windows messages. This situation generally has a negative performance impact and may even lead to the application becoming non responsive or memory usage accumulating continually over time. To avoid this
It appears to be deadlocking even though the code only contains a simple C# timer: See Snippet Below:
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();
}
/// <summary>
/// Initialise a timer with a timer interval configured from app.config. Enable the timer and
/// register an appropriate event handler
/// </summary>
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();
}
As far as I know the timer should run, elapse and then initialise again, I can see no local reason for a deadlock.
I am aware of how to turn this error msg off but feel that this is not a solution, instead it is masking the problem.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
这是一个无限循环。 您需要让您的应用程序至少每 60 秒发送一次一些消息,以防止发生此异常。
尝试偶尔调用 System.Threading.Thread.CurrentThread.Join(10) 一次。 您还可以执行其他调用来传递消息。
This is an infinite loop. You need to let your application pump some messages at least once every 60 seconds to prevent this exception to happen.
Try calling System.Threading.Thread.CurrentThread.Join(10) once in a while. There are other calls you can do that let the messages pump.
如果您认为自己肯定没有遇到死锁情况,可以将其关闭:
Visual Studio 中的“调试”->“异常”->“托管调试助手”菜单,然后取消选中 ContextSwitchDeadlock
You can turn this off if you think you've definitely not got a deadlock situation:
Debug->Exceptions->Managed Debug Assistants menu in Visual Studio and uncheck the ContextSwitchDeadlock
看来您每次调用 InitialiseTimer 时都会添加一个新的事件处理程序。 这样,m_Timer_Elapsed 将被调用与添加的次数一样多。
您应该只添加一次事件处理程序。
It seems that you are adding a new event handler each time you call InitialiseTimer. That way m_Timer_Elapsed will be called as many times as it has been added.
You should add the event handler just one time.
如果您的应用程序挂起或没有响应,即使您取消选中上下文切换死锁复选框。 将以下行放在方法调用或 for 循环之前。
在 C#
和 VB.NET / VB / ASP.NET中
If your application hangs or not reponse even after you uncheck the box against contextswitchdeadlock. Put the following line before call of method or for loop.
In C#
and VB.NET / VB / ASP.NET
几个想法/问题:
1)代码片段看起来你的间隔是每 1 秒(而不是评论中提到的 5 秒)。
2)最大的问题是
RequestWork()
在做什么?如果不知道
RequestWork()
正在做什么,我们就无法真正评论为什么您会看到 ContextSwitchDeadlock。关于此方法需要考虑的事情
a) 需要多长时间?
b) 它是否访问 GUI 元素?
MSDN 对 Elapsed 的一些评论:
-和-
我想既然你有一个 1 秒的计时器,你可能想看看 RequestWork 中发生了什么,看看它花了多长时间。
Couple thoughts/questions:
1) The code snippet looks like your interval is every 1 second (not 5 as mentioned in the comments).
2) The big question is what is
RequestWork()
doing?Without knowing what
RequestWork()
is doing, we can't really comment on why you are seeing a ContextSwitchDeadlock.Somethings to think about with respect to this method
a) how long does it take?
b) is it accessing GUI elements?
Some MSDN comments on Elapsed:
-and-
I'm thinking since you have a 1 second timer, you might want to look into what happens in RequestWork and see how long its taking.