visual - messageboxoptions c#
¿Bombeando mensajes de Windows durante una operación larga? (7)
Como sé, esto sucede solo con el depurador adjunto. Nunca obtendrás esta excepción en producción.
Recibo el siguiente mensaje en una gran operación que estoy ejecutando:
El CLR no ha podido realizar la transición del contexto COM 0x1fe458 al contexto COM 0x1fe5c8 durante 60 segundos. El subproceso que posee el apartamento / contexto de destino es más probable, ya sea haciendo una espera sin bombeo o procesando una operación muy larga sin bombear los mensajes de Windows. Esta situación generalmente tiene un impacto negativo en el rendimiento e incluso puede hacer que la aplicación deje de responder o que el uso de la memoria se acumule continuamente a lo largo del tiempo. Para evitar este problema, todos los subprocesos de apartamento de una sola rosca (STA) deben usar primitivas de espera de bombeo (como CoWaitForMultipleHandles) y bombear mensajes de manera rutinaria durante operaciones de larga duración.
¿Cómo envío mensajes de Windows para que este error ya no ocurra en operaciones largas?
Debe procesar su operación de ejecución prolongada en un subproceso separado para evitar que se congele la interfaz de usuario. Esto también resolverá el problema anterior
El método tradicional de win32 es:
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 );
}
}
Pero supongo que está utilizando .NET.
Sé que esto se solicitó hace años, pero espero que esto ayude a otros en el futuro. Si no quiere preocuparse por hacer un trabajo en segundo plano o enviar mensajes, una simple solución es simplemente actualizar algo en la interfaz de usuario. Por ejemplo, tengo una herramienta que solo uso, por lo que no me importa si usa el subproceso de la interfaz de usuario. Así que simplemente actualizo un textbox.text en la IU a lo que sea que esté trabajando. Aquí hay un fragmento del código. Esta es una forma muy hacky, y probablemente incorrecta de hacerlo profesionalmente, pero funciona.
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.
}
Si esto sucede dentro de un depurador, puede deberse a ContextSwitchDeadlock MDA, que puede desactivar (use la ventana Excepciones en Visual Studio). Sin embargo, es indicativo de un problema mayor: no debe realizar operaciones de larga duración en su hilo de interfaz de usuario.
Tiendo a usar Application.DoEvents en estos escenarios. Aunque no sé si eso funcionará en tu situación. Requiere una referencia a System.Windows.Forms pero también funcionará en aplicaciones de consola.
Alternativamente, puede probar múltiples subprocesos de sus aplicaciones.
No está claro exactamente cuál es el contexto: ¿está realizando alguna tarea de larga ejecución en el subproceso de la interfaz de usuario de una aplicación WinForms o WPF? Si es así, no hagas eso: usa BackgroundWorker
, o ejecuta la tarea en el grupo de hilos o un nuevo hilo directamente (posiblemente utilizando Control.Invoke/BeginInvoke
o Dispatcher
si necesitas actualizar la interfaz de usuario). Si su gran operación usa el componente COM que se queja, será más difícil ...