ver ventana titulo pantalla mostrar mensaje ejemplos control comandos comando botones barra c# multithreading winforms process devexpress

c# - ventana - mostrar mensaje en pantalla cmd



"No responde" en el título de la ventana cuando se ejecuta en un nuevo proceso (8)

Esto se debe a que llama a un método de larga ejecución de forma sincrónica en la secuencia principal de la aplicación. Como su aplicación está ocupada, no responde a los mensajes de Windows y está marcada como (No responde) hasta que finaliza.

Para manejar esto haga su copia de forma asíncrona, por ejemplo, utilizando una Tarea como una solución más simple.

Task task = new Task(() => { gridView.Enabled = false; gridView.CopyToClipboard(); gridView.Enabled = true; }); task.Start();

Deshabilite su cuadrícula para que nadie pueda cambiar los valores en la GUI. El resto de su aplicación sigue siendo receptiva (¡puede tener efectos secundarios!).

Tengo un método de larga ejecución que debe ejecutarse en el hilo de UI. (Devex - gridView.CopyToClipboard() )

No necesito que la interfaz de usuario sea receptiva mientras copio y agregué una pantalla de bienvenida para que el usuario no se aburra.

Cuando ejecuto este programa, todo está bien.

El problema se inicia cuando ejecuto un programa diferente que a su vez inicia un nuevo proceso y ejecuta el programa en él. Después de unos segundos de copiar el título dice (No responde) y el cursor del mouse muestra ocupado, por supuesto se aclara en pocos segundos, pero me gustaría deshacerme de él, ya que le da al usuario la sensación errónea de que el programa es defectuoso.

¿Hay alguna forma de establecer el "Tiempo de espera" de un proceso que creo?

EDITAR:

El programa principal llama al siguiente código:

fillsProcess = new Process(); fillsProcess.StartInfo.FileName = Application.ExecutablePath; fillsProcess.Start();

En el proceso fillills, cuando se hace clic en un botón determinado, se llama al siguiente código:

gridViewToCopy.CopyToClipboard();

Esta línea de código tarda un tiempo en procesarse y después de unos segundos, la ventana del proceso fillills no responde porque este método se ejecuta en el hilo de la interfaz de usuario.

EDITAR el 2do:

Aparentemente (y realmente bastante comprensible)

gridViewToCopy.CopyToClipboard();

No es el único método que causa este problema. Muchos métodos Devex tienen que ejecutarse en el hilo de UI (por ejemplo, clasificación de datos, filtrado de datos)

Así que gracias a todos los que ofrecieron una solución específica (que funcionó o no), pero mi pregunta original aparece de nuevo:

¿Hay alguna forma de cambiar el tiempo de espera o de alguna manera controlar todo el fiasco de "No responde"?


Podría iniciar el proceso oculto y luego verificar si responde y devolverlo a la vista cuando se complete ... su pantalla de inicio mostraría que aún está "respondiendo".

Process proc = new Process(); proc.StartInfo.FileName = "<Your Program>.exe" proc.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;

Editar: también puede crear un evento Timer viendo el otro proceso y desplegar su propia lógica de tiempo de espera

DateTime dStartTime = DateTime.Now; TimeSpan span = new TimeSpan(0, 0, 0); int timeout = 30; //30 seconds private void timer1_Tick(Object myObject, EventArgs myEventArgs) { while (span.Seconds < timeout) { Process[] processList = Process.GetProcessesByName("<YourProcess.exe>"); if (processList.Length == 0) { //process completed timer1.Stop(); break; } span = DateTime.Now.Subtract(dStartTime); } if (span.Seconds > timeout) { Process[] processList = Process.GetProcessesByName("<YourProcess.exe>"); //Give it one last chance to complete if (processList.Length != 0) { //process not completed foreach (Process p in processList) { p.Kill(); } } timer1.Stop(); } }

Edit2

Puede usar pInvoke "ShowWindow" para lograr ocultar y mostrar la ventana también después de que se inició

private const int SW_HIDE = 0x00; private const int SW_SHOW = 0x05; [DllImport("user32.dll")] static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);


Hay varios enfoques posibles

  • Ocultar el formulario principal para el período de la operación
  • De alguna manera, clone / serialice el control y páselo a un hilo con otro despachador de UI
  • Obtenga las celdas seleccionadas a través de gridView.GetSelectedCells() y luego coloque sus contenidos en el portapapeles de forma asíncrona

Sería más útil si has cargado la biblioteca GridView alguna parte, para que podamos mirar dentro.


No estoy seguro de si su usuario necesita ver la pantalla que "no responde". Si no es necesario, puede intentar dejar que la aplicación se ejecute en segundo plano después de que se cierre el hilo principal de esta aplicación; o puedes minimizar la aplicación.

Si es necesario ver la aplicación y que parezca estar funcionando, ¿puede segmentar la función "copiar al portapapeles" de tal manera que esté enhebrada y contenga una matriz o la vista de cuadrícula y un rango de índice. La ventaja de esto es que su hilo principal en su proceso subordinado nunca se cuelgue. La desventaja es que a la gente no le gusta trabajar con subprocesos y delega en C #.


Bien, el artefacto de ventana ''No responde'' y la ventana que has descrito son solo síntomas de ejecutar una actividad a largo plazo en tu subproceso de interfaz de usuario. El subproceso de interfaz de usuario está bloqueado, por lo que la interfaz de usuario está congelada. No hay forma de evitar esto. Para ser sincero, es simplemente ''afortunado'' que tu aplicación parezca tan receptiva como lo es.

Por lo que puedo ver, cada solución que se ha descrito aquí es solo un truco para evitar el hecho de que el hilo de UI está congelado. No hagas esto Arregla tu programa para que el hilo de UI no se congele.

Pregúntese: ¿ realmente necesitan mis usuarios copiar todas las filas de esta vista? ¿Pueden los datos ser filtrados de alguna manera para limitar las filas? De lo contrario, existe una propiedad llamada MaxRowCopyCount que limita el número de filas que se copian, ¿se puede aprovechar sin romper su flujo de trabajo?

Finalmente, si todo lo demás falla, ¿hay algún otro medio que pueda usar (tal vez un archivo intermedio), para que los datos puedan copiarse en un hilo de fondo?


El tiempo de espera, documentado en IsHungAppWindow, no se puede cambiar. No use estado global para administrar un problema local.

Tienes que optimizar la parte que causa la falta de respuesta. Por ejemplo, utilizar el almacenamiento en caché, la cuadrícula virtual (DevExpress lo llama "modo servidor"), paginar, delegar la clasificación a un filtro de ibindinglistview que hace una consulta de base de datos (usa índice de base de datos) en lugar de ordenar en memoria (sin indexación) o implementar IAsyncOperation en los datos del portapapeles, por lo que solo necesitaría completar los datos cuando el usuario pegue.


Me temo que la solución más simple es crear su propio CopyToClipboard() donde usted en su bucle for, de vez en cuando, haga una Application.DoEvents , que mantiene el hilo de la interfaz de usuario en respuesta.

Supongo que la mayoría de las licencias de DevExpress tienen el código fuente disponible, por lo que probablemente pueda copiar pegar la mayoría si lo hace.

Como conoce los datos, probablemente pueda hacer un procedimiento mucho más simple que el genérico que utiliza DevExpress.

Me gusta esto:

const int feedbackinterval = 1000; private void btnCopy_Click(object sender, EventArgs e) { StringBuilder txt2CB = new StringBuilder(); int[] rows = gridView1.GetSelectedRows(); if (rows == null) return; for (int n = 0; n < rows.Length; n++) { if ((n % feedbackinterval) == 0) Application.DoEvents(); if (!gridView1.IsGroupRow(rows[n])) { var item = gridView1.GetRow(rows[n]) as vWorkOrder; txt2CB.AppendLine(String.Format("{0}/t{1}/t{2}", item.GroupCode, item.GroupDesc, item.note_no??0)); } } Clipboard.SetText(txt2CB.ToString()); }


Puede usar la función DisableProcessWindowsGhosting win32:

[DllImport("user32.dll")] public static extern void DisableProcessWindowsGhosting();

En realidad, esto no evita que la ventana se congele, pero evita que el texto "No responda" en el título.