2010-08-19 6 views
0

J'utilise .net 2.0 et j'ai créé un formulaire (System.Windows.Forms.Form) pour afficher des informations lors de tâches longues. Lorsque je démarre une tâche longue, je crée une nouvelle instance de ce formulaire, appelez .Show() et démarrez BackgroundWorker. Mais même si j'utilise un BackgroundWorker pour faire le travail, le formulaire apparaît en effet, mais bloque immédiatement et ne répond pas jusqu'à ce que l'arrière-plan ait fini, i.d. le formulaire apparaît mais le contenu (un gif et une zone de texte) n'est pas affiché?C#: Blocage de formulaire popup malgré BackgroundWorker

La chose étrange est, cela ne se produit pas lorsque le travail pour BackgroundWorker est aussi intensif!?! Comment venir?

Exemple:

private void UpdateReportingTab() 
{ 
    //p is an instance variable; Progressbar is just a simple form control 
    //showing the passed message 
    p = new Progressbar("Loading Data..."); 
    p.Show(); 
    BackgroundWorker bw = new BackgroundWorker(); 
    bw.WorkerSupportsCancellation = true; 
    bw.DoWork += new DoWorkEventHandler(bw_DoWork); 
    bw.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bw_RunWorkerCompleted); 
    bw.RunWorkerAsync(); 
} 

private void bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) 
{    
    p.BeginInvoke(new MethodInvoker(p.Close)); 
} 

private void bw_DoWork(object sender, DoWorkEventArgs e) 
{ 
    if (this.InvokeRequired) 
    { 
     this.BeginInvoke(new MethodInvoker(delegate() 
     { 
      //long running database queries, whose results update text fields 
      //while text fields are filled p show "no response" 
      TextEditItems.Text = Convert.ToString(itemsDao.getItemCount()); 
      .... 
     } 
    } 
} 

Merci!

Andi

Répondre

3

Parce que vous ne courez pas efficacement un travailleur de fond, mec;)

Le travailleur de fond INVOQUE DANS LA MAIN FILET - qui remet le travail dans le thread principal de l'interface utilisateur où.

Vous NE DEVEZ PAS REVENIR AU BESOIN.

particulièrement:

  • Faire la longue requête de base de données active, récupérer les résultats
  • Invoquez ensuite de nouveau dans le thread d'interface utilisateur de mettre à jour les TextEditItems

Dès que vous invoquez en arrière, vous êtes de retour sur le fil de l'interface utilisateur - dans votre cas, le travailleur de l'arrière-plan therad ne fait que l'invoquer de retour ... ce qui rend le travailleur de fond insensé. En utilisant BeginInvoke, vous exécutez le code sur le thread d'interface utilisateur en utilisant

+1

Whoa, stable sur les chapeaux là-bas ... – cofiem

+0

Merci, vous avez raison. Comment ai-je pu manquer ça :)? –

2

Votre BackgroundWorker est inutile ici, le bw_DoWork reviendra immédiatement et l'interface utilisateur sera gelée.

Si vous avez besoin des données des contrôles, récupérer avant de commencer leBackgroundWorker, et faire le travail sur le fil BGW plutôt que d'appeler Invoke ou BeginInvoke

Questions connexes