Хороший способ создать простой цикл в C#?

У меня есть приложение, которое устанавливает FileSystemWatcher. Это должно работать бесконечно.

Каков наилучший способ запустить его в режиме ожидания?

Я сейчас занимаюсь

FileSystemWatcher watch = ... //setup the watcher
watch.EnableRaisingEvents = true;
while (true) 
{
    Thread.Sleep(int.MaxValue);
}

который, кажется, работает (т.е. захватывает события и не использует ядро ​​в занятом цикле).

Любая другая идиома? Есть проблемы с этим подходом?

5 ответов

Решение

Как я понял из вашего комментария, ваше приложение должно работать бесконечно, и это консольное приложение, запускаемое другим исполняемым файлом.

Лучше использовать Console.ReadLine вместо зацикливания. или используйте метод Monitor.Wait, чтобы заблокировать поток на неопределенный срок

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

FileSystemWatcher.WaitForChanged выполняет блокировку (синхронно). Абсолютно нет необходимости в свободном цикле, особенно потому, что вы обрабатываете события. Примечание. По умолчанию EnableRaisingEvents имеет значение true. Поэтому все, что вам нужно сделать, это добавить компонент в форму. Там нет простоя петли. Потоков нет, потому что об этом заботится компонент.

Я понимаю, что вы используете консольное приложение. Поэтому вы можете создать следующий цикл. Опять же, нет необходимости в холостом цикле. Компонент заботится обо всех деталях.

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

[обновление] "Примечание. EnableRaisingEvents по умолчанию имеет значение true". Согласно исходному коду Microsoft, это верно только в том случае, если компонент FileSystemWatcher помещен в конструктор. Как показано ниже:

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

            // set EnableRaisingEvents to true at design time so the user
            // doesn't have to manually. We can't do this in 
            // the constructor because in code it should
            // default to false. 
            if (Site != null && Site.DesignMode) 
                EnableRaisingEvents = true;
        } 
    }

[обновление] Звонок WaitForChanged устанавливает EnableRaisingEvents непосредственно до и после System.Threading.Monitor.Wait заявления.

Thread.Sleep() будет делать то, что вы хотите. Но в основном вы должны заблокировать, используя метод ОС, который будет следовать вашей желаемой стратегии. Например. Console.ReadLine() или мьютекс, который удаляется вашим обработчиком событий, чтобы уйти.

Вам не нужно убивать приложение, чтобы оно закрылось.

Если вы встраиваете код в форму, то, по крайней мере, форму можно легко убить, с разумной загрузкой ОС, когда вы ее не используете.

Если вы отметите поток, в котором этот цикл работает, как фоновый поток ( свойство Thread.IsBackground), то он должен работать нормально (программа завершится, когда завершатся все не фоновые потоки).

Я не понимаю... Зачем тебе и холостой цикл? Вы хотите, чтобы ваше приложение работало бесконечно?

Тогда, почему бы вам не создать службу Windows или приложение, которое можно запустить в системном трее?

Затем то, что я хотел бы сделать, это создать класс, который просто делает это:

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;
   }

}
Другие вопросы по тегам