2009-05-05 9 views
1

J'essaie d'exécuter une tâche en arrière-plan en vérifiant une base de données pour un certain nombre d'enregistrements dans une table, et si le numéro a changé depuis la dernière vérification, obtenir ces enregistrements, et faire travaille dessus. En utilisant le code suivant, j'obtiens un débordement de pile au bout de deux heures environ. L'application ne fait rien pendant cette période, vérifie simplement et aucun travail n'est ajouté à la base de données.C# .net looping débordement de pile de threads

private Thread threadTask = null; 
private int recordCount = 0; 

private void threadTask_Start() 
{ 
    if (threadTask == null) { 
     threadTask = new Thread(taskCheck); 
     threadTask.Start(); 
    } 
} 

private void taskCheck() 
{ 
    int recordCountNew = GetDBRecordCound(); 
    if (recordCountNew != recordCount) 
    { 
     taskDo(); 
     recordCount = recordCountNew; // Reset the local count for the next loop 
    } 
    else 
     Thread.Sleep(1000); // Give the thread a quick break 

    taskCheck();   
} 

private void taskDo() 
{ 
    // get the top DB record and handle it 
    // delete this record from the db 
} 

Quand il déborde, il y a une tonne de taskCheck() dans la pile d'appels. Je devine que taskCheck() ne se termine jamais jusqu'à ce que taskCheck() se termine, ergo débordement, et donc pourquoi ils restent tous dans la pile. Ce n'est évidemment pas la bonne façon de procéder, alors qu'est-ce que c'est?

+0

N'appelez-vous pas taskCheck() en bas de taskCheck()? Le trait de soulignement est une faute de frappe, non? – lotsoffreetime

+0

Je pense que je vois d'où vous venez. Non - C#/.NET ne s'applique pas TCO - vous devez faire la boucle manuellement. – viraptor

Répondre

9

Vous obtenez un débordement de pile car à la fin de la vérification des tâches, vous appelez à nouveau taskCheck. Vous ne quittez jamais la fonction taskCheck, vous finissez par appeler de plus en plus jusqu'à ce que votre pile déborde. Ce que vous devez faire est d'avoir une boucle while dans taskCheck à la place:

private void taskCheck() 
{ 
    while(true) 
    { 
     int recordCountNew = GetDBRecordCound(); 
     if (recordCountNew != recordCount) 
     { 
      taskDo(); 
      recordCount = recordCountNew; // Reset the local count for the next loop 
     } 
     else 
      Thread.Sleep(1000); // Give the thread a quick break 
    } 
} 
+3

Il devrait aussi avoir un try {} catch (ThreadAbortException) {} finally {} bloquer. –

+0

bon point. Si une exception est levée (appel de base de données?), Le flux d'exécution quittera la boucle while et la boucle while cessera d'être exécutée. J'informe généralement l'utilisateur dans un journal des messages ou pop up si cela se produit. Alternatives? – MedicineMan

+0

Il y a une autre gestion de base de données en cours, que je vais utiliser pour contrôler la valeur 'true' s'il y a un problème. – mattdwen

1

Je suppose que vous avez task_Check(), vous voulez dire en fait taskCheck() (ou vice-versa). Autrement dit, vous appelez la méthode taskCheck() recursively. En évitant la discussion de l'architecture ici, vous pouvez supprimer cet appel et faire en sorte que threadTask_Start() répète le processus une fois dans une boucle while.

+0

Était une faute de frappe, corrigé. – mattdwen

Questions connexes