contextswitchdeadlock - PullRequest
       42

contextswitchdeadlock

3 голосов
/ 02 декабря 2008

Во время отладки моей программы в 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();

    }



    /// <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();
    }

Насколько я знаю, таймер должен запуститься, истечь и затем снова инициализироваться, я не вижу никакой локальной причины тупика.

Я знаю, как отключить эту ошибку, но чувствую, что это не решение, а маскировка проблемы.

Ответы [ 5 ]

5 голосов
/ 02 декабря 2008

Вы можете отключить это, если считаете, что определенно не попали в тупиковую ситуацию:

Отладка-> Исключения-> Меню управляемых помощников отладки в Visual Studio и снимите флажок ContextSwitchDeadlock

4 голосов
/ 05 марта 2009

Это бесконечный цикл. Чтобы предотвратить возникновение этого исключения, вы должны разрешить приложению отправлять некоторые сообщения не реже одного раза в 60 секунд. Попробуйте вызывать System.Threading.Thread.CurrentThread.Join (10) время от времени. Существуют и другие звонки, которые позволяют сообщениям качать.

1 голос
/ 09 февраля 2010

Если ваше приложение зависает или не отвечает, даже после того, как вы снимите флажок против contextxtswitchdeadlock. Поставьте следующую строку перед вызовом метода или для цикла.

In C #

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

и VB.NET / VB / ASP.NET

DoEvents()
1 голос
/ 02 декабря 2008

Кажется, что вы добавляете новый обработчик событий каждый раз, когда вызываете InitialiseTimer. Таким образом, m_Timer_Elapsed будет вызываться столько раз, сколько было добавлено. Вы должны добавить обработчик событий только один раз.

0 голосов
/ 29 января 2009

Пара мыслей / вопросов:

1) Фрагмент кода выглядит так, будто ваш интервал составляет 1 секунду (а не 5, как указано в комментариях). 2) Большой вопрос в том, что делает RequestWork()

Не зная, что делает RequestWork(), мы не можем прокомментировать, почему вы видите ContextSwitchDeadlock.

Нечто обдумать в отношении этого метода а) сколько времени это займет? б) это доступ к элементам графического интерфейса?

Некоторые комментарии MSDN к Elapsed:

Если вы используете таймер с пользователем элемент интерфейса, такой как форма или контролировать, назначить форму или контроль который содержит таймер к Свойство SynchronizingObject, чтобы событие маршалируется пользователю интерфейсная нить.

-и-

Истекшее событие возникает на Тема ThreadPool. Если обработка Истекшее событие длится дольше, чем Интервал, событие может быть возбуждено снова в другой теме ThreadPool. Таким образом, обработчик события должен быть возвратный.

Я думаю, поскольку у вас есть 1-секундный таймер, вы можете посмотреть, что происходит в RequestWork, и узнать, сколько времени занимает его.

...