Перекачка Сообщений Windows Во Время Длительной Работы?
Я получаю следующее сообщение о большой операции, которую я выполняю:
среда CLR не смогла перейти из контекста COM 0x1fe458 в COM контексте 0x1fe5c8 за 60 секунд. Этот поток, которому принадлежит назначение контекст/квартира, скорее всего или делать non нагнетая ожидание или обработка очень длинного хода деятельность без нагнетая окон сообщения. Эта ситуация обычно имеет отрицательное влияние на производительность и может даже привести к приложение становится не реагировать или использование памяти накапливается постоянно с течением времени. К избегайте этой проблемы, все одиночные резьбовые резьбы квартиры (STA) следует использовать прокачку wait primitives (например, CoWaitForMultipleHandles) и регулярно качать сообщения во время long выполнение операций.
Как отправлять сообщения windows, чтобы эта ошибка больше не возникала при длительных операциях?
7 ответов
неясно, что именно контекст-вы выполняете какую-то длительную задачу в потоке пользовательского интерфейса приложения WinForms или WPF? Если это так, не делайте этого - используйте BackgroundWorker
или запустите задачу в пуле потоков или новом потоке напрямую (возможно, используя Control.Invoke/BeginInvoke
или Dispatcher
Если вам нужно обновить UI). Если ваша большая операция использует компонент COM, который жалуется, это будет сложнее...
Как я знаю, это происходит только с подключенным отладчиком. Вы никогда не получите это исключение в производстве.
Я предпочитаю использовать приложение.Функция doevents в этих сценариях. Я не знаю, сработает ли это в вашей ситуации. Это требует Ссылки на систему.Окна.Формы, но также будут работать в консольных приложениях.
в качестве альтернативы вы можете попробовать многопоточность вашего приложения.
Если это происходит внутри отладчика, это может быть связано с ContextSwitchDeadlock MDA, который можно отключить (используйте окно исключений в Visual Studio). Однако это указывает на большую проблему-вы не должны выполнять длительные операции в потоке пользовательского интерфейса.
традиционный метод 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 );
}
}
но я понимаю, что вы используете .Сеть.
вы должны обрабатывать свою длительную работу в отдельном потоке, чтобы избежать замораживания пользовательского интерфейса. Это также решит проблему выше
Я знаю, что это было задано много лет назад, но надеюсь, что это поможет другим вниз по дороге. Если вы не хотите беспокоиться о выполнении фонового рабочего или перекачки сообщений, простым обходным путем является просто обновление чего-то в пользовательском интерфейсе. Например, у меня есть инструмент, который только я использую, поэтому мне все равно, использует ли он поток пользовательского интерфейса. Поэтому я просто обновляю текстовое поле.текст в пользовательском интерфейсе к тому, над чем я работаю. вот фрагмент кода. Это очень хакерский и, вероятно, неправильный способ сделать это профессионально, но это работает.
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.
}