2011-04-04 19 views
6

Tengo el evento de botón seguimiento clic:C# - orden de procesamiento de código - comportamiento extraño

private void btnRun_Click(object sender, EventArgs e) 
    { 
     label1.Visible = true; 

     if (SelectDatabase()) 
     { 
      if (string.IsNullOrEmpty(txtFolderAddress.Text)) 
       MessageBox.Show("Please select a folder to begin the search."); 
      else 
      { 

       if (cbRecurse.Checked == false || Directory.GetDirectories(initialDirectory).Length == 0) 
       { 
        CheckSingleFolder(); 
       } 
       else 
       { 
        CheckSingleFolder(); 
        directoryRecurse(initialDirectory); 
       } 

           } 
     } 


    } 

Efectivamente, hace unos pocos cheques y luego empieza algunos recursividad de directorios en busca de archivos específicos. Sin embargo, la primera línea de código para hacer que la etiqueta sea visible no se produce hasta después de que los directorios hayan sido recursados. ¿Alguien sabe por qué sería esto?

Gracias.

+0

intente actualizar su formulario si su función lo contiene, podría ayudar. 'form1.refresh();' – Prix

Respuesta

8

Está haciendo todo lo que está dentro del hilo de la interfaz de usuario, lo cual es una muy mala idea: la interfaz de usuario no actualiza, reacciona a eventos, etc. hasta que termina.

Debe usar un hilo de fondo y actualizar la UI con progreso, etc. usando Control.BeginInvoke, o tal vez usar un BackgroundWorker.

Básicamente, hay dos reglas de oro en WinForms (y similar con WPF/Silverlight):

  • No haga nada que puede tomar una cantidad significativa de tiempo en el hilo de interfaz de usuario
  • Don' t toque los elementos de interfaz de usuario desde cualquier subproceso otra que el hilo de interfaz de usuario
+0

¿Cuál sería la mejor manera de esperar a que termine el nuevo hilo?Tengo otro método que tiene que esperar hasta que la recursión haya terminado. Si utilizo un hilo separado y luego utilizo algo como while (thread.isalive) {}, obviamente bloquea el hilo hasta que el nuevo hilo haya terminado. ¿Qué recomendarías? Gracias. –

+0

@Darren: Haga que el código de manejo de archivos marque una llamada al hilo de la interfaz de usuario, llamando a cualquier método que necesite continuar luego (por ejemplo, volver a habilitar el botón, etc.). –

+0

Excelente gracias. Así que simplemente, por ejemplo, uso algo como tal: btnRun.Invoke ((MethodInvoker) delegate {// Run Method}); –

1

todo su método se ejecuta actualmente como una unidad de bloqueo - agregue un Application.DoEvents() como una solución alternativa, pero realmente debería estar haciendo este tipo de procesamiento en un hilo de fondo, es decir, utilizando un trabajador de fondo.

+3

Blech. Application.DoEvents es un truco: este código no debería ejecutarse en el hilo de la interfaz de usuario para empezar. –

+0

gaah Estaba escribiendo ese – BrokenGlass

+0

Y un hack muy * peligroso *, en eso. Me alegra que hayas agregado esa aclaración; escapó por poco de mi voto negativo. ;-) Hay demasiadas respuestas que hacen recomendaciones mal concebidas para usar 'Application.DoEvents'. –

1

El código se está ejecutando en el mismo hilo que está dibujando su interfaz de usuario. Por lo tanto, mientras el código se está ejecutando, su UI no se vuelve a dibujar. Una vez que el código de clic de botón ha finalizado, la UI se vuelve a dibujar y label1 se dibuja de forma invisible.

Puede mover el código en una secuencia separada utilizando, por ejemplo, Task o BackgroundWorker. Sin embargo, no puede establecer directamente las propiedades de IU a partir de un hilo diferente, por lo que deberá tener cuidado de configurar sus propiedades de IU a partir del hilo de IU o see this question para saber cómo actualizar la GUI desde otro hilo.

1

la vista no se actualiza hasta que el bloque de código terminado. Entonces propondría un BackgroundWorker para la parte de recursión.

1

La explicación: la etiqueta se establece en visible y está invalidada (necesita repintar) pero la bomba de mensajes de Windows no comienza a volver a pintar hasta que esté inactiva. Entonces tu código lo bloquea.

Una solución simple es llamar al label1.Update() justo después de configurarlo.

Una mejor solución es mover el código que consume mucho tiempo a un subproceso (Backgroundworker).