4 Stimmen

Guter Weg, eine Leerlaufschleife in C# zu erstellen?

Ich habe eine App, die einen FileSystemWatcher einrichtet. Es sollte dauerhaft laufen.

Wie ist der beste Weg, um es in einer Leerlaufschleife laufen zu lassen?

Derzeit mache ich Folgendes

FileSystemWatcher watch = ... // den Watcher einrichten
watch.EnableRaisingEvents = true;
while (true) 
{
    Thread.Sleep(int.MaxValue);
}

Was zu funktionieren scheint (dh, erfasst die Ereignisse und verwendet keinen Kern in einer beschäftigten Schleife).

Gibt es ein anderes Sprachidiom? Gibt es Probleme mit diesem Ansatz?

9voto

AMissico Punkte 21179

FileSystemWatcher.WaitForChanged ist blockierend (synchron). Es besteht absolut kein Bedarf an einer Leerlaufschleife, insbesondere weil Sie Ereignisse behandeln. Beachten Sie, dass EnableRaisingEvents standardmäßig auf true gesetzt ist. Daher müssen Sie nur das Komponente einem Formular hinzufügen. Es gibt keine Leerlaufschleife. Es gibt kein Threaden, weil sich die Komponente darum kümmert.

Ich verstehe, dass Sie eine Konsolenanwendung verwenden. Daher können Sie die folgende Schleife erstellen. Auch hier ist keine Leerlaufschleife erforderlich. Die Komponente kümmert sich um alle Details.

    Do
        Dim i As WaitForChangedResult = Me.FileSystemWatcher1.WaitForChanged(WatcherChangeTypes.All, 1000)
    Loop Until fCancel

[update] "Beachten Sie, dass EnableRaisingEvents standardmäßig auf true gesetzt ist." Laut dem Microsoft-Quellcode ist dies nur dann der Fall, wenn die FileSystemWatcher-Komponente auf ein Designerfeld gezogen wird. Wie unten gezeigt:

    /// 
    /// 
    /// 
    [Browsable(false)] 
    public override ISite Site {
        get { 
            return base.Site; 
        }
        set { 
            base.Site = value;

            // Setzen Sie EnableRaisingEvents auf true zur Designzeit, damit der Benutzer
            // dies nicht manuell tun muss. Wir können dies nicht im Konstruktor machen, weil es im Code
            // standardmäßig auf false stehen sollte.
            if (Site != null && Site.DesignMode) 
                EnableRaisingEvents = true;
        } 
    }

[update] Der Aufruf von WaitForChanged setzt EnableRaisingEvents unmittelbar vor und nach den System.Threading.Monitor.Wait Anweisungen.

6voto

Ahmed Punkte 6941

Wie ich aus Ihrem Kommentar verstanden habe, muss Ihre Anwendung unendlich laufen und es handelt sich um eine Konsolenanwendung, die von einer anderen aus ausgeführt wird.

Es ist besser, Console.ReadLine anstelle einer Schleife zu verwenden. oder die Monitor.Wait-Methode, um den Thread unendlich zu blockieren

object sync = new object();
lock(sync)
Monitor.Wait(sync);

2voto

Spence Punkte 27536

Thread.Sleep() wird tun, was du willst. Aber im Grunde solltest du blockieren, indem du eine OS-Methode verwendest, die bei deiner gewünschten Strategie aufwacht. Zum Beispiel ein Console.ReadLine() oder bei einem Mutex, der von deinem Ereignishandler getroffen wird, um wegzugehen.

Du solltest deine App nicht töten müssen, um sie zu beenden.

Wenn du den Code in ein Formular einbettet, dann kann zumindest das Formular ordentlich beendet werden, mit einer vernünftigen OS-Last, wenn du es nicht benutzt.

2voto

chris166 Punkte 4781

Wenn Sie den Thread markieren, in dem diese Schleife läuft, als Hintergrundthread (Thread.IsBackground-Eigenschaft), sollte es gut funktionieren (das Programm wird beendet, wenn alle nicht-Hintergrundthreads beendet sind)

0voto

Frederik Gheysels Punkte 54908

Ich verstehe nicht ... Warum möchtest du eine Leerlaufschleife haben? Möchtest du, dass deine Anwendung unendlich läuft?

Dann, warum erstellst du nicht einen Windows-Dienst oder eine Anwendung, die im System-Tray ausgeführt werden kann?

Dann würde ich eine Klasse erstellen, die nur das tut:

public class Foo
{
   private FileSystemWatcher _fs;

   private volatile bool _stopped = false;

   public Foo()
   {
       _fs = new FileSystemWatcher();
       ...
   }

   public void Start()
   {
       _stopped = false;
       Thread t = new Thread (new ThreadStart(DoWork));
       t.Start();
   }

   private void DoWork()
   {
       while( !_stopped )
       {
           Thread.Sleep(1);
       }
   }

   public void Stop()
   {
       _stopped = true;
   }

}

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X