2010-06-15 3 views
2

je tente de démarrer multi thread mais je ne peux pas il me renvoie l'erreur: Opération croisée pas valide: thread 'listBox1' a été créé pour contrôler l'accès extérieur d'un autre thread était.Comment peut résoudre "opération Cross-thread non valide"?

MyCodes:


    public DataTable dTable; 
     public DataTable dtRowsCount; 
     Thread t1; 
     ThreadStart ts1; 
    void ExcelToSql() 
     { 
      // SelectDataFromExcel(); 
      ts1 = new ThreadStart(SelectDataFromExcel); 
      t1 = new Thread(ts1); 
      t1.Start(); 
     }
void SelectDataFromExcel() 
     { 
      string connectionString = @"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=C:\Source\Addresses.xlsx;Extended Properties=""Excel 12.0;HDR=YES;"""; 
      OleDbConnection excelConnection = new OleDbConnection(connectionString); 
         string[] Sheets = new string[] { "Sayfa1"}; 
      excelConnection.Open(); // This code will open excel file.    
      OleDbCommand dbCommand; 
      OleDbDataAdapter dataAdapter; 
      // progressBar1.Minimum = 1; 

      foreach (var sheet in Sheets) 
      { 
       dbCommand = new OleDbCommand("select * From[" + sheet + "$]", excelConnection); 
       //progressBar1.Maximum = CountRowsExcel(sheet).Rows.Count; 
       // progressBar2.Value = i + 1; 
       System.Threading.Thread.Sleep(1000); 
       **listBox1.Items.Add("Tablo ismi: "+sheet.ToUpper()+"Satır Adeti: "+CountRowsExcel(sheet).Rows.Count.ToString()+" ");** 
       dataAdapter = new OleDbDataAdapter(dbCommand); 
       dTable = new DataTable(); 
       dataAdapter.Fill(dTable); 
       dTable.TableName = sheet.ToUpper(); 
       dTable.Dispose(); 
       dataAdapter.Dispose(); 
       dbCommand.Dispose(); 
       ArrangedDataList(dTable); 
       FillSqlTable(dTable, dTable.TableName); 
      } 

      excelConnection.Close(); 
      excelConnection.Dispose(); 
     }

Répondre

3

Vous ne pouvez pas mettre à jour un composant d'interface utilisateur à partir d'un fil non-UI. Utilisez TaskScheduler.FromCurrentSynchronizationContext pour marshal l'appel au thread UI.

+1

Vous apprenez quelque chose tous les jours, ce que j'adore au sujet SO. Ils ont glissé quelques goodies dans 4.0 n'ont-ils pas. – Spence

4

Un contrôle créé dans le thread d'interface utilisateur n'est pas accessible dans un autre thread de manière normale. Veuillez créer un délégué et appeler le délégué en utilisant control.Invoke.

L'échantillon de méthode fournie ci-dessous peut être utilisé pour permettre la visibilité sur un bouton quel que soit le contexte de fil que vous êtes.

private void EnableButtonVisibility(Button btn, bool enable)  
{  
    if (!btn.InvokeRequired)  
    {  
btn.Visible = enable;  
    } 
    else  
    {  
     btn.Invoke(new EnableButtonVisibilityHandler(EnableButtonVisibility), btn, enable);  
    }  
}  
delegate void EnableButtonVisibilityHandler(Button btn, bool enable); 
+0

C'est une solution que j'utiliserai occasionnellement. – Meiscooldude

+2

Pas besoin de créer un délégué, vous pouvez utiliser 'Action ' qui est avilable dans la bibliothèque de classes de base. –

+0

+1 Oui. Cela peut être utilisé pour ajouter une méthode en ligne. –

5

Le fil en arrière-plan ne peut pas accéder aux composants de l'interface utilisateur.

Dans les formes multithread, j'inclure le code comme ceci:

private delegate void InvokeAction(); 
    private void DoUI(InvokeAction call) { 
     if (IsDisposed) { 
      return; 
     } 
     if (InvokeRequired) { 
      try { 
       Invoke(call); 
      } catch (InvalidOperationException) { 
       // Handle error 
      } 
     } else { 
      call(); 
     } 
    } 

Puis de mon fil d'arrière-plan, je peux le code comme ceci:

// Stuff in other thread 
    myVar = GetFromDb(); 
    DoUI(() => { 
     // Access UI components here 
     listBox1.Items.Add(myVar); 
    }); 
    // More other thread 
+1

points tripple si je pouvais l'attribuer pour cette réponse .. Code réutilisable est la voie à suivre! – Christian

Questions connexes