2009-11-20 4 views
0

Possible en double:
Locking main() threadGarder un fil vivant dans une application C#

Ci-dessous vous trouverez mon code, principal appelle deux fils, l'un initie un gestionnaire d'événements qui renvoie les valeurs de clés de registre après avoir été modifiées. L'autre met en place une minuterie qui écrit les modifications dans un fichier XML toutes les quelques minutes. Fondamentalement, je cherche à exécuter l'écriture encore et encore pendant que je souhaite que le lancement du gestionnaire d'événements ne s'exécute qu'une seule fois, mais reste ouvert pour accepter les événements. Est-ce qu'il y a un moyen de faire ça? Des gestionnaires d'attente qui permettront toujours au code de fonctionner, etc.? S'il vous plaît noter qu'il s'agit d'une application en arrière-plan, sans console car je ne veux pas d'interaction de l'utilisateur avec le système (je sais qu'un service est la solution, mais quand j'ai posé des questions similaires une application et une application ont plus de sens pour la façon dont je veux l'exécuter/l'utiliser.)

public class main 
{ 
    static void Main(string[] args) 
    { 
     runner one = new runner(); 
     runner two = new runner(); 

     Thread thread1 = new Thread(new ThreadStart(one.TimerMeth)); 
     Thread thread2 = new Thread(new ThreadStart(two.start)); 

     thread1.Start(); 
     thread2.Start(); 
    } 
} 

public class runner 
{ 
    RegistryValueChange valuechange; 
    List<regkey> RegKeys = new List<regkey>(); 
    static object locker = new object(); 

    public void start() 
    { 
      if (File.Exists("C:\\test.xml")) 
      { 
       file load = new file(); 
       RegKeys = load.read(RegKeys); 
      } 

      string hiveid = "HKEY_USERS"; 
      WindowsIdentity identity = WindowsIdentity.GetCurrent(); 
      string id = identity.User.ToString(); 

      string key1 = id + "\\\\Software\\\\Microsoft\\\\Windows NT\\\\CurrentVersion\\\\Windows Messaging Subsystem\\\\Profiles\\\\Outlook\\\\0a0d020000000000c000000000000046"; 
      List<string> value1 = new List<String> { "01020402", "test" }; 

      valuechange = new RegistryValueChange(hiveid, key1, value1); 
      valuechange.RegistryValueChanged += new EventHandler<RegistryValueChangedEventArgs>(valuechange_RegistryValueChanged); 

      file test = new file(); 
      test.checkfile("C:\\test.xml"); 
    } 

    void valuechange_RegistryValueChanged(object sender, RegistryValueChangedEventArgs e) 
    { 
    } 

    public void TimerMeth() 
    { 
      System.Timers.Timer timer = new System.Timers.Timer(); 

      timer.Elapsed += new ElapsedEventHandler(OnElapsedTime); 

      timer.Interval = 300000; 

      timer.Enabled = true; 
    } 

    private void OnElapsedTime(object source, ElapsedEventArgs e) 
    { 
     lock (locker) 
     { 
      file write = new file(); 
      write.write(RegKeys); 
     } 
    } 
} 
+0

Avez-vous déjà demandé et accepté une réponse à cette même question? http://stackoverflow.com/questions/1722932/locking-main-thread –

+0

LOL! Et j'étais occupé à composer une jolie réponse ... disant principalement la même chose que la réponse précédente ... –

Répondre

1
  • Vous n'avez pas besoin de créer un thread juste pour démarrer le timer. Vous pouvez simplement démarrer la minuterie dans votre thread principal. Sa fonction s'exécutera sur un thread à partir du pool de threads.

  • Je ne vois pas pourquoi vous devez créer un fil pour la fonction start(). Il doit être exécuté au moins partiellement avant votre premier travail de minuterie. Ainsi, vous pouvez exécuter RegKeys = load.read(RegKeys); (et probablement d'autres codes de start) dans le thread principal. Si vous insistez pour l'exécuter dans un thread séparé, assurez-vous que RegKeys est initialisé. Cela peut être fait par, par exemple. réglage ManualResetEvent après l'initialisation RegKeys et en attente de ce ManualResetEvent dans le rappel de la minuterie.

  • Vous devez arrêter le temporisateur à la sortie du processus.

  • vous devez attendre l'arrêt du thread commencé à utiliser la méthode Thread.Join ou en attente sur certains WaitHandle (ManualResetEvent par exemple) étant mis en fil sur la finition.

0

Vous avez plusieurs problèmes avec votre code. D'abord votre méthode Start() devrait faire une boucle. Si ce n'est pas le cas, il s'exécutera une fois et puis sortira, finissant ainsi le fil.

Votre application principale démarre simplement les threads, puis se termine, donc lorsque le code atteint le crochet fermant dans votre application, il se termine simplement. Vous devez attendre que les threads se terminent avant de quitter votre méthode Main.

En outre, l'ensemble du processus peut être difficile. Tout d'abord, Timers exécuter dans le thread principal au moyen d'une interruption et un message de fenêtre à la boucle de message de la fenêtre, que vous n'avez pas puisque c'est une application console, au moment où l'événement timer déclenche votre application sera certainement terminée. Here Vous pouvez voir comment utiliser une minuterie dans une application de console (notez qu'il n'est pas nécessaire de la créer dans un thread séparé). Notez que le délégué est appelé à partir d'un thread de pool de threads, évitant ainsi votre création dans le coureur "deux". Enfin, tenez compte du fait que vous devrez garder votre application principale en cours d'exécution jusqu'à ce que quelque chose arrive pour la faire quitter. C'est-à-dire, vous devrez configurer une boucle sur votre Main pour permettre à votre application d'attendre que quelque chose se produise, qu'il s'agisse d'une entrée utilisateur, de messages réseau ou autre ... En gros, vous attendez la commande "Quitter".