2010-01-05 18 views
5

Ya busqué en el foro pero ninguna pregunta se ajusta a mi problema, creo ...¿Por qué BackgroundWorker_RunWorkerCompleted no actualiza la GUI?

Uso un BackgroundWorker para manejar una operación que consume mucho tiempo. Una vez que finaliza esta operación, un botón debe configurarse como habilitado para que el usuario pueda realizar otra operación.

Estoy usando WPF y estoy siguiendo el patrón de MVVM, por lo que no tengo acceso directo a este botón. Tengo que llamar a un método en el controlador de eventos BackgroundWorker_RunWorkerCompleted que establece una propiedad, que representa los botones estado habilitado, en verdadero.

Todo funciona bien excepto una cosa: el botón solo se vuelve a dibujar después de que p. Ej. haga clic en la ventana (o maximice la ventana, ...). Eso es muy molesto y me llevó todo el día para deshacerse de este comportamiento, pero no puedo encontrar una solución ...

El controlador de eventos BackgroundWorker_RunWorkerCompleted se parece a esto:

void fileLoadBackgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) { 
     SetButtonToEnabled(); } 

Alguien alguna idea de cómo para arreglar este problema?

Editar:

El botón está vinculado a un comando:

<Button Name="btnLoadTargetFile" Command="{Binding Path=LoadTargetCommand}" .../> 

Este comando es un RelayCommand como Smith declaró en su blog (http://msdn.microsoft.com/en-us/magazine/dd419663.aspx) y se ve así:

public RelayCommand LoadTargetCommand 
    { 
     get 
     { 
      if (loadTargetCommand == null) 
      { 
       loadTargetCommand = new RelayCommand(param => this.OnRequestLoadFile(BusinessLogic.CustomTypes.TreeType.Target), param => this.CanLoadTarget); 
      } 
      return loadTargetCommand; 
     } 
     set { loadTargetCommand = value; } 
    } 

this.CanLoadTarget está establecido en true por SetButtonToEnabled(); Método

Edición 2:

el siguiente código 'funciona':

fileLoadBackgroundWorker.RunWorkerAsync(argumentList); 
while(fileLoadBackgroundWorker.IsBusy) 
    System.Windows.Forms.Application.DoEvents(); 
SetButtonToEnabled(); 

pero que es algún tipo de código realmente peligroso y feo ...

+0

Cuando establece la propiedad en verdadero, plantea el evento 'PropertyChanged' (es decir, ¿su modelo de vista implementa' INotifyPropertyChanged' correctamente)? –

+0

Si llamo a ese método después de fileLoadBackgroundWorker.RunWorkerAsync() todo funciona bien, así que no creo que ese sea el problema? – lakai

+0

Solo por curiosidad, ¿está utilizando alguna modificación de WMI en la forma o el borde del formulario (color del borde, etc.)? –

Respuesta

2

Althought es imposible explicar su problema, usted podría tratar de añadir

System.Windows.Forms.Application.DoEvents(); 

o

Dispatcher.Invoke(new Action(delegate { }), DispatcherPriority.Background); 

hasta el final de su llamada a la función SetButtonToEnabled (después de configurar el botón habilitado en true). Parece que el usuario de fondo llama al evento Completo, pero la GUI no es refrescante.

Here es un ejemplo completo que utiliza el Backgroundworker en WPF. Tal vez quieras echarle un vistazo y asegurarte de que tus cosas se vean igual.

También puede consultar Asynchronous Threading with Background Worker Object. Este es un buen ejemplo del uso de Dispatcher y Backgroundworker

El WPF Threading Model es otra gran fuente para verificar.

+0

gracias por tu comentario! mi código se ve como el ejemplo, excepto que no tengo acceso directo a los botones debido al patrón de MVVM que uso – lakai

+0

¿Podría publicar el código de SetButtonToEnabled? No creo que sea un problema con Backgroundworker, ya que mencionaste que se llama a Complete. Es probablemente algo que estás haciendo en el hilo principal. ¿Qué estás haciendo mientras el proceso se ejecuta en segundo plano? – SwDevMan81

+1

Es posible que desee comprobar InvalidateRequerySuggested: http://msdn.microsoft.com/en-us/library/system.windows.input.commandmanager.invalidaterequerysuggested.aspx Intente agregar esto al final de SetButtonToEnabled – SwDevMan81

1

Su problema probablemente no tiene nada que hacer con el BackgroundWorker. Si llama al método SetButtonToEnabled directamente desde el hilo principal, probablemente verá el mismo comportamiento. Reemplace la llamada al RunWorkerAsync con una a SetButtonToEnabled para probar esto.

Un par de los comentaristas sugirieron que mirara su implementación INotifyPropertyChanged, esto suena como un buen consejo.

+0

gracias por su respuesta! Si llamo SetButtonToEnabled en el hilo principal todo funciona bien ... – lakai

+0

¿Puede confirmar que se está produciendo el evento RunWorkerCompleted? ¿Un punto de quiebre que estableces allí recibe un golpe? –

+0

sí lo hace, se llega al punto de interrupción – lakai

Cuestiones relacionadas