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

    }



    /// <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 ответов

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

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

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

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

В C#

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

и VB.NET / VB / ASP.NET

DoEvents()

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

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

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

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

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

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

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

-а также-

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

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

Другие вопросы по тегам