Подтвердить что ты не робот

Перекачка сообщений Windows во время длительной работы?

Я получаю следующее сообщение о большой операции, которую я запускаю:

Среда CLR не может перейти из контекста COM 0x1fe458 в COM контекст 0x1fe5c8 в течение 60 секунд. поток, которому принадлежит место назначения контекст/квартира, скорее всего, либо без ожидания перекачки, либо обработка очень длительная работа без перекачки Windows Сообщения. Эта ситуация обычно имеет отрицательное влияние на производительность и может даже привести к тому, что приложение станет невосприимчивость или использование памяти постоянно накапливаясь с течением времени. к избегайте этой проблемы, все одиночные резьба по резьбе (STA) следует использовать подкачки ожидания перекачки (например, CoWaitForMultipleHandles) и регулярно перекачать сообщения в течение длительного времени выполняемые операции.

Как отправлять сообщения Windows, чтобы эта ошибка больше не выполнялась при длительных операциях?

4b9b3361

Ответ 1

Непонятно, в чем заключается контекст: выполняете ли вы какую-то долгосрочную задачу в потоке пользовательского интерфейса приложения WinForms или WPF? Если это так, не делайте этого - используйте BackgroundWorker или запустите задачу в пуле потоков или в новом потоке напрямую (возможно, используя Control.Invoke/BeginInvoke или Dispatcher, если вам нужно обновить интерфейс). Если ваша большая операция использует COM-компонент, который жалуется, это будет сложнее...

Ответ 2

Как я знаю, это происходит только с прикрепленным отладчиком. Вы никогда не получите это исключение в производстве.

Ответ 3

Я склонен использовать Application.DoEvents в этих сценариях. Я не знаю, будет ли это работать в вашей ситуации. Он требует ссылки на System.Windows.Forms, но также будет работать в консольных приложениях.

В качестве альтернативы вы можете попробовать многопоточность ваших приложений.

Ответ 4

Если это происходит внутри отладчика, это может быть связано с ContextSwitchDeadlock MDA, которое вы можете отключить (используйте окно "Исключения" в Visual Studio). Однако это указывает на большую проблему - вы не должны выполнять длительные операции с вашим потоком пользовательского интерфейса.

Ответ 5

Традиционный метод win32:

void PumpMessages()
{
    MSG msg;
    for( ;; ) {
        if( !PeekMessage( &msg, 0, 0, 0, PM_REMOVE ) ) {
            return;
        }
        if( msg.message == WM_QUIT ) {
            s_stopped = true;
            return;
        }
        TranslateMessage( &msg );
        DispatchMessage( &msg );
    }
}

Но я понимаю, что вы используете .NET.

Ответ 6

Вы должны обработать свою длительную операцию в отдельном потоке, чтобы избежать замораживания пользовательского интерфейса. Это также решит проблему выше

Ответ 7

Я знаю, что это задавали несколько лет назад, но надеясь, что это поможет другим в будущем. Если вы не хотите беспокоиться о том, чтобы делать фонового работника или перекачивать сообщения, простое обходное решение просто обновляет что-то в пользовательском интерфейсе. Например, у меня есть инструмент, который только я использую, поэтому мне все равно, использует ли он поток пользовательского интерфейса. Поэтому я просто обновляю textbox.text в пользовательском интерфейсе, над чем я работаю. здесь приведен фрагмент кода. Это очень хакерский и, вероятно, неправильный способ сделать это профессионально, но он работает.

for (int i = 0; i < txtbxURL.LineCount; i++)
{
    mytest.NavigateTo(mytest.strURL);
    mytest.SetupWebDoc(mytest.strURL);
    strOutput = mytest.PullOutPutText(mytest.strURL);
    strOutput = mytest.Tests(strOutput);
    mytest.CheckAlt(mytest.strURL);
    mytest.WriteError(txtbxWriteFile.Text);
    txtblCurrentURL.Text = mytest.strURL;
    //This ^^^ is what is being updated, which keeps the thread from throwing the exception noted above.
}