2011-08-07 4 views
0

J'ai un formulaire et il n'y a aucun contrôle. J'essaie d'obtenir les contrôles de la base de données pour que mon projet soit lent je pense que je peux utiliser le filetage mais j'obtiens une erreur.Erreur de multithreading

void Form_Load(object sender,EventArgs e) 
    { 

    SqlDataAdapter adap=new SqlDataAdapter("Select * from MyControls"); 
    DataTable dt=new DataTable(); 

    adap.Fiil(dt); 

    foreach(DataRow dr in dt.Rows) 
    { 
     ThreadStart ts=delegate{ Sample1(dr) }; 
Thread th=new Thread(ts); 
th.start(); 

    } 

    } 

    public void Sample1(DataRow dr) 
    { 
    this.Invoke(new AddControlsDelegate(AddControls),new object[] {dr }); 
    } 
    public void AddControls(DataRow dr) 
    { 
    TextBox tx=new TextBox(); 
    tx.Name=dr["Id"].ToString(); 
    this.Controls.Add(tx); 

    } 

public delegate void AddControlsDelegate(DataRow dr); 

Je suis tryin avec ce code .Mais il DonT work.It ajoutant même temps le contrôle deux fois, 3 fois, 4 fois

Où est le mal mon? grâce

Répondre

2

Vous refermant sur la variable de boucle:

foreach(DataRow dr in dt.Rows) 
{ 
    ThreadStart ts=delegate{ Sample1(dr) }; 
    ... 
} 

Vous créez une fermeture de la boucle variables, non sa valeur au moment - car le fil ne sera lancé une peu de temps après, la boucle est terminée et chaque thread utilisera la valeur de la variable de boucle à ce moment-là, qui sera la dernière rangée.

plutôt créer une variable locale dans la boucle et l'utiliser dans votre délégué:

foreach(DataRow dr in dt.Rows) 
{ 
    DataRow currentRow = dr; 
    ThreadStart ts=delegate{ Sample1(currentRow) }; 
    Thread th=new Thread(ts); 
    th.start(); 
} 

Voir aussi "Closing over the loop variable considered harmful"

+0

fonctionner Merci un lot.But contrôles doivent venir asceding « Id » parfois son est pas asceding – YardimaIhtiyaciOlan

+1

peut-être vous devriez changer le SQL et comprennent une 'ORDER BY Id' ... – Yahia

+0

@YardimaIhtiyaciOlan: En plus de la En ordonnant en SQL, il n'y a pas de contrôle sur le moment où les threads s'exécutent réellement - l'ordre n'est pas garanti, pour cela vous aurez besoin d'une approche différente. En outre, votre code actuel n'a pas beaucoup de sens - la surcharge de l'utilisation de plusieurs threads ne vaut pas la peine pour ce que vous faites réellement. – BrokenGlass

0

Mis à part le fait que vous avez créé une fermeture sur une variable de boucle at-il un couple de problèmes assez importants avec votre approche générale. D'abord, créer un thread pour chaque ligne dans le DataTable n'est pas une bonne idée. La chose est de créer et de démarrer des discussions est une dépense et consomme beaucoup de ressources. Vous devez choisir judicieusement comment et quand vous créez des discussions. Par exemple, avoir 10 000 threads en cours d'exécution (en supposant qu'il y ait 10 000 lignes correspondantes dans le DataTable) ne fonctionnera pas très bien.

Mais, même si vous changiez une approche plus saine en utilisant la ThreadPool via QueueUserWorkItem, les délégués asynchrones ou en démarrant une nouvelle Task il y a encore un autre problème. L'opération que vous vouliez réaliser sur un autre thread finit par être ramenée sur le thread UI. L'utilisation de threads dans ce cas ne sert absolument à rien. En fait, cela ne fait qu'empirer les choses puisque le fil ne fait aucun travail utile. Et cela nécessite une opération de marshaling coûteuse via Control.Invoke pour ne rien faire. En d'autres termes, votre thread d'interface utilisateur indique à un thread de travail de faire quelque chose et le thread de travail se retourne et dit "Je ne veux pas, vous le faites à la place."

Une meilleure approche serait d'exécuter la commande SQL et de remplir le DataTable sur un autre thread. Une fois cela terminé, vous pouvez ensuite ajouter tous les contrôles TextBox au formulaire à partir du thread UI. En fait, faire quelque chose avec un élément d'interface utilisateur doit être fait à partir du thread d'interface utilisateur de sorte que vous n'avez vraiment pas beaucoup d'options acceptables ici.