2010-08-06 4 views
0

J'ai un petit problème avec ce code:passage sur Threads C#ERREUR

Cette méthode est la « principale » de l'application:

private Thread main_process; 
private Clases.GestorTR processor; 

public void begin() 
{ 
    processor = new Clases.GestorTR(); 
    main_process = new Thread(new ThreadStart(processor.ExecuteP)); 
    main_process.Start(); 
} 

J'ai créé un thread pour traiter d'autres "Transacction Threads" pour éviter de bloquer l'interface graphique. Ce est la méthode ExecuteP, sur l'objet de processeur:

public void ExecuteP() 
{ 
// Readed an DataTable with BD transacction, filled with numbers 
foreach (DataRow dr in dtResults.Rows) 
{ 
    int Local_number = Convert.toInt32(dr["autonum"].ToString()); 
    ThreadStart starter; 
    starter = delegate { new QueryBD.QueryCounter(Local_number); }; 
    new Thread(starter).Start(); 
} 
} 

Cette méthode est QueryCounter de classe QueryBD:

.... 
private void QueryCounter(int _counter) 
    { 
     logs.log("ON QUERY_PROCESS: " + _counter); 
    } 
... 

Maintenant, le problème. Lors de l'appel du délégué, certains threads traversent des paramètres. Par exemple, dans la méthode foreach, le journal affiche correct (1,2,3,4,5,6,7,8) mais, dans la méthode QueryCounter (appelée à chaque fois avec le nouveau thread, le journal affiche (1,1 , 1,4,5,6,6,8) par exemple, j'ai aussi essayé d'utiliser des verrous, mais le problème est le même.Egalement tester avec la méthode ThreadPool avec le même résultat Je pense que je suis manquant quelque chose dans la boucle foreach, parce que si je déboguer le premier terme, le fil est en route, mais sans action dans le journal

Merci !,

Répondre

0

Vous devriez essayer de changer certaines parties de votre code comme ça.:

public void ExecuteP() 
{ 
    QueryBD facade = new QueryBD. 
    foreach (DataRow dr in dtResults.Rows) 
    { 
    int Local_number = Convert.toInt32(dr["autonum"].ToString()); 
    new Thread(new ParameterizedThreadStart(facade.QueryCounter)).Start(Local_number); 
    } 
} 

public void QueryCounter(object _counter) 
{ 
    ... 
} 

J'espère que cela fonctionne.

Btw. J'ai créé un objet appelé façade et je passe cet objet à différents threads. Il peut également entraîner des effets secondaires s'il y aura enfilez partie sensible du code dans l'objet de façade, de sorte que vous pouvez aussi envisager de verrouillage là:

public void QueryCounter(object _counter) 
{ 
    lock(this) 
    { 
     // 
    } 
} 

ou de fournir de nouveaux QueryBD à chaque fil, mais il peut affecter les performances .

EDIT: Hey, 4 choses:

  1. Lors de l'utilisation ParametrizedThread, la variable passée pour démarrer la méthode du fil (thread.Start(variable)) est copié au moment de l'appel. Une telle variable copiée est ensuite utilisée dans le thread enfant. Le délégué anonyme fonctionne différemment. Il conserve la référence à la variable. Ainsi, lorsque la variable est utilisée par le thread enfant, elle peut être modifiée en fonction de l'heure de votre thread parent. C'est pourquoi vous avez eu un comportement imprévu.

  2. Une meilleure explication vous pouvez trouver ici: Differing behavior when starting a thread: ParameterizedThreadStart vs. Anonymous Delegate. Why does it matter?.

  3. La performance dépend. Si la création de votre objet est lourde (par exemple, il crée une nouvelle connexion à DB chaque fois qu'il est créé) les performances peuvent être sérieusement affectées par la création de nombreux objets de ce type - c'est là que le verrouillage est le meilleur. Si la création de l'objet est légère, vous pouvez créer autant d'objets que vous le souhaitez. Ça dépend.

  4. Si vous souhaitez que votre code soit exécuté dans l'ordre défini, vous ne devez pas utiliser de threads du tout. Si vous souhaitez conserver l'ordre d'exécution, l'appel séquentiel est le bon moyen - voir Hans Passant explication.

+0

Hi! Je n'utilisais pas ParameterizedThreadStart pour maintenir un code "plus propre", et évitait d'analyser l'objet comme un tableau de chaînes pour obtenir tous les paramètres dans la méthode .... mais j'avais tort. Maintenant, je fais des recherches pour savoir pourquoi ThreadPool et le mode anonyme de méthode de délégué ne fonctionnent pas, aucune idée ??? A propos du verrou, qu'en est-il des performances sur: UTILISATION DE VERROUILLAGE avec 1 objet de base VS. Fournir une nouvelle instance à chaque thread? Penser en vitesse, fournir la nouvelle instance chaque fois n'est pas le moyen le plus rapide? Merci beaucoup, – Jabab

+0

Processus complet avec invocation WS et accès BD. La vitesse et plusieurs demandes sont un « must »: Avec objet nouveau sur chaque appel: DÉPART 16: 00: 08,8915628 FINI 16: 00: 12,0278610 TEMPS TOTAL: 3,1362982 avec serrure et objet de base simple: COMMENCEZ 16 : 02: 33.3375315 FINI 16: 02: 38.9863682 TEMPS TOTAL: 5.6488367 – Jabab

+0

Hey, vérifiez la partie EDIT dans ma réponse. Cette section de commentaire est à court pour cela. Prends soin. – jwaliszko

Questions connexes