2010-09-08 2 views
2

Je suis bloqué avec le problème ci-dessus. J'ai eu beaucoup de solutions mais aucune d'elles ne fonctionnait pour moi. S'il vous plaît trouver ci-joint mon codeC# - Barre de progression [Threading] Opération cross-thread non valide: Contrôle 'progressBar' accessible à partir d'un thread autre que le thread sur lequel il a été créé

private void btnRunQuery_Click(object sender, EventArgs e) 
    { 
     try 
     { 

      Thread ProcessThread = new Thread(Process); 
      ProcessThread.Start(); 

      Thread.CurrentThread.Join(); 
     } 
     catch 
     { 
      Debug.WriteLine("Error in model creation"); 
      Console.WriteLine("Error in model creation"); 
     } 
     finally 
     { 
      //dsModel = null; 
     } 
    } 


private void Process() 
    { 

     using (var dataContext = new IControlerDataContext()) 
     { 
      dataContext.EnlistTransaction(); 

      IItemPropertyRepository itemPropertyRepository = ObjectContainer.Resolve<IItemPropertyRepository>(); 
      IList<ItemProperty> itemPropertyCollection = itemPropertyRepository.LoadAll(); 
      totalCount = itemPropertyCollection.Count; 
      currentCount = 0; 

      foreach (var itemProperty in itemPropertyCollection) 
      { 
       try 
       { 
        message = string.Empty; 
        currentCount++; 
        if (itemProperty.DeletedDate == null && (itemProperty.MetaItemProperty.ValueType == MetaItemPropertyValueType.MetaItemTableProperty || itemProperty.MetaItemProperty.ValueType == MetaItemPropertyValueType.MetaItemTableMultiSelectProperty)) 
        { 
         //Property refresh issue in only applicable for table and multitable property. 
         //Need to filter the itemproperty for Table and multitable select property. 
         message = ProcessItemProperty(itemProperty); 
         //txtLogDetails.Text += message + Environment.NewLine; 
         //txtLogDetails.Refresh(); 
         //txtLogDetails.ScrollToCaret(); 
        } 
        //Log(message); 
        //progressBar.Value = (Int32)(currentCount * 100/totalCount); 
        //progressBar.Refresh(); 
        Invoke(new MyDelegate(ShowProgressBar), (Int32)(currentCount * 100/totalCount)); 

       } 
       catch (Exception ex) 
       { 
        txtLogDetails.Text += "EXCEPTION ERROR : " + itemProperty.Id.ToString(); 
        dataContext.RollBackTransaction(); 
       } 
      } 
      dataContext.CompleteTransaction(); 
     } 
    } 

delegate void MyDelegate(int percentage); 
    private void ShowProgressBar(int percentage) 
    { 
     progressBar.Value = percentage; 
     progressBar.Refresh(); 
     //txtLogDetails.Text = message; 
    } 

Quand il exécute "Invoke (nouvelle MyDelegate (ShowProgressBar), (Int32) (currentCount * 100/totalCount));" cette ligne est hors de portée. Il va à l'intérieur et n'est jamais revenu. et aussi n'a pas pris dans l'exception.

Quelqu'un peut-il m'aider s'il vous plaît?

Merci, Mahesh

Répondre

4

Le contrôle progressBar doit être accessible à partir du fil qu'il a été créé. Utilisez BeginInvoke.

Je remplacerais cette ligne ...

Invoke(new MyDelegate(ShowProgressBar), (Int32)(currentCount * 100/totalCount)); 

... par celui-ci ...

this.progressBar.BeginInvoke( 
    (MethodInvoker)delegate() { 
     this.progressBar.Value = 
      Convert.ToInt32(currentCount * 100/totalCount); }); 

Ou vous pouvez remplacer ces lignes ...

progressBar.Value = percentage; 
     progressBar.Refresh(); 
     //txtLogDetails.Text = message; 

... par ces lignes ...

this.progressBar.BeginInvoke( 
    (MethodInvoker)delegate() { 
    progressBar.Value = percentage; 
    progressBar.Refresh(); 
    //txtLogDetails.Text = message; 

    }); 
+0

Au-dessus du code pour mon contrôle, dois-je insérer dans la méthode "Process()"? Sinon, où dois-je insérer ce code? – Mahesh

+0

J'ai mis à jour ma réponse pour correspondre à votre code –

+0

Salut Pierre, Merci pour la réponse rapide – Mahesh

0

Je pense que le problème est que vous bloquez le thread UI avec Thread.Join. Thread.Join continuera en théorie à pomper les messages de l'interface utilisateur, mais en réalité, cela ne fonctionne pas toujours.

voir le blog de Chris Brumme here. En particulier

L'effet net est que nous pompons toujours les appels COM en attente pour entrer dans votre STA. Et tous SendMessages à toutes les fenêtres seront desservis. Mais la plupart des PostMessages seront retardés jusqu'à ce que vous ayez fini de bloquer.

Vous devez laisser finir l'événement bouton et ravoir le nouveau poste de fil un message quand il est fait (par exemple en utilisant BackgroundWorker ou un autre cadre async)

(Votre déclaration de capture est inutile de toute façon, car il n'acceptera que des exceptions de création de threads.)

Questions connexes