2010-01-08 6 views
2

Je souhaite que mon programme attende en permanence un déclencheur afin d'effectuer la tâche suivante.while (true) ou tcp listen: qu'est-ce qui est le plus efficace?

  1. Une option est la mise en pool: en utilisant une boucle infinie, par ex. while (true)
  2. OU, TCP écoute-t-il sur un port avec un délai d'attente relativement plus long.

Je voudrais savoir laquelle de ces deux techniques serait la plus efficace pour garder mon application en vie? Je pense que l'exécution de while (true) serait un tueur et que tcp listen pourrait être une option de santé puisque tcp listen utiliserait l'interruption matérielle?

De plus, dans les applications .net winform, nous avons la méthode Application.Run() qui maintient l'application en vie. Si quelqu'un sait ce que cette méthode fait en interne partage. PS: J'ai déjà considéré l'option msmq ici (ce qui équivaut à tcp listen) mais je ne veux pas de dépendance sur msmq.

+0

À propos de la partie «Aussi»: veuillez en faire une question distincte. –

+4

Qu'attendez-vous exactement? Si vous attendez une connexion TCP, l'écoute est la meilleure, sinon l'un des objets attendus, par ex. AutoResetEvent, serait mieux. Pour WaitHandles, voir http://www.yoda.arachsys.com/csharp/threads/waithandles.shtml – Ryan

Répondre

5

À moins que vous n'attendiez que quelque chose se produise sur un port TCP/IP, vous ne devriez pas (ab) utiliser Listen.

Une méthode efficace est AutoResetEvent que vous signalez lorsque vous souhaitez déclencher le traitement d'une tâche. Cela fera dormir votre thread jusqu'à ce qu'il doive faire quelque chose, sans aucune interrogation.

class TaskProcessor 
{ 
    AutoResetEvent newTaskHandle = new AutoResetEvent(false); 
    Queue<Task> taskQueue = new Queue<Task>(); 
    object syncRoot = new object(); 

    public void ProcessTasks() 
    { 
     while (true) 
     { 
      newTaskHandle.WaitOne(); 

      Task task = null; 

      lock (syncRoot) 
      { 
       if (taskQueue.Count > 0) 
       { 
        task = taskQueue.Dequeue(); 
       } 
      } 

      // Do task 
     } 
    } 

    public void AddTask(Task task) 
    { 
     lock (syncRoot) 
     { 
      taskQueue.Enqueue(task); 
      newTaskHandle.Set(); 
     } 
    } 
} 

Cela soulèvera probablement la question de savoir comment annuler les tâches de traitement. Vous pouvez utiliser plus d'un seul WaitHandler (dont AutoResetEvent hérite) et attendre que l'un d'eux de se produire:

WaitHandle[] handles = new WaitHandle[] { newTaskHandle, stopHandle }; 

int signalledHandle = WaitHandle.WaitAny(handles); 

Sinon, vous pouvez introduire un booléen simple et réutiliser le même événement. Cela peut être préférable si vous voulez vous assurer que toutes les tâches sont traitées avant de s'arrêter.

+0

Je pense qu'ils doivent créer un nouveau badge appelé "Vote Squatter" "Répondre Placeholder" pour des réponses comme celle-ci.:) –

+1

John: en effet .. il est parfois un peu triste de voir que la meilleure réponse est ajoutée plus tard et n'obtient * aucun * vote, parce que les gens ne lisent que les premiers. C'est pourquoi j'ai pris l'habitude de fournir rapidement une réponse courte, que je développe ensuite. – Thorarin

3

Quelle est la source de ce déclencheur? Même application, même PC, réseau?

même application: utiliser AutoResetEvent Une autre application sur le même PC: utiliser un Mutex ou Semaphore

Oui TCP écouter serait la meilleure option lorsque la source de déclenchement est une autre machine.

Si votre application WinForms ne se termine pas lorsque vous fermez les dernières fenêtres hou très probablement un peu de fil à gauche en cours d'exécution

+0

Bon point sur la synchronisation interprocess en utilisant un Mutex nommé. Il y a vraiment beaucoup de possibilités. Une entrée supplémentaire empêcherait de devoir les expliquer tous :) – Thorarin

0

j'envisager de mettre votre section de code dans un thread séparé et laisser le fil ne l'attente de libérer votre interface utilisateur, il suffit d'avoir votre interface utilisateur écouter l'événement:

var tcpConnectionMade = new AutoResetEvent(false); 
System.Threading.ThreadPool.QueueUserWorkItem(delegate 
{ 
    // listen for TCP connection 
    ... 
    // once connected 
    tcpConnectionMade.Set(); 
}); 

// wait for TCP connection 
WaitHandle.WaitOne(tcpConnectionMade); 

// do something when connected... 
Questions connexes