上下文切换死锁

发布于 2024-07-10 04:29:38 字数 1590 浏览 5 评论 0原文

在 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

白云悠悠 2024-07-17 04:29:38

这是一个无限循环。 您需要让您的应用程序至少每 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.

陌路终见情 2024-07-17 04:29:38

如果您认为自己肯定没有遇到死锁情况,可以将其关闭:

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

灰色世界里的红玫瑰 2024-07-17 04:29:38

看来您每次调用 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.

万人眼中万个我 2024-07-17 04:29:38

如果您的应用程序挂起或没有响应,即使您取消选中上下文切换死锁复选框。 将以下行放在方法调用或 for 循环之前。

在 C#

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

和 VB.NET / VB / ASP.NET中

DoEvents()

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#

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

and VB.NET / VB / ASP.NET

DoEvents()
一页 2024-07-17 04:29:38

几个想法/问题:

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

如果不知道 RequestWork() 正在做什么,我们就无法真正评论为什么您会看到 ContextSwitchDeadlock。

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

MSDN 对 Elapsed 的一些评论:

如果您对用户使用计时器
界面元素,例如表单或
控件,分配表单或控件
其中包含定时器到
SynchronizingObject 属性,以便
该事件被编组给用户
接口线程。

-和-

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

我想既然你有一个 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:

If you use the Timer with a user
interface element, such as a form or
control, assign the form or control
that contains the Timer to the
SynchronizingObject property, so that
the event is marshaled to the user
interface thread.

-and-

The Elapsed event is raised on a
ThreadPool thread. If processing of
the Elapsed event lasts longer than
Interval, the event might be raised
again on another ThreadPool thread.
Thus, the event handler should be
reentrant.

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文