O evento FileSystemWatcher Changed é gerado duas vezes

Eu tenho um aplicativo onde estou procurando um arquivo de texto e se houver alterações feitas no arquivo que estou usando o manipulador de events OnChanged para manipular o evento. Eu estou usando o NotifyFilters.LastWriteTime mas ainda o evento está sendo demitido duas vezes. Aqui está o código.

 public void Initialize() { FileSystemWatcher _fileWatcher = new FileSystemWatcher(); _fileWatcher.Path = "C:\\Folder"; _fileWatcher.NotifyFilter = NotifyFilters.LastWrite; _fileWatcher.Filter = "Version.txt"; _fileWatcher.Changed += new FileSystemEventHandler(OnChanged); _fileWatcher.EnableRaisingEvents = true; } private void OnChanged(object source, FileSystemEventArgs e) { ....... } 

No meu caso, o OnChanged é chamado duas vezes, quando eu mudo o arquivo de texto version.txt e o salvo.

    Eu tenho medo que este é um bug / recurso bem conhecido da class FileSystemWatcher . Isto é da documentação da class:

    Você pode notar em determinadas situações que um único evento de criação gera vários events criados que são manipulados pelo seu componente. Por exemplo, se você usar um componente FileSystemWatcher para monitorar a criação de novos arquivos em um diretório e testá-lo usando o Bloco de Notas para criar um arquivo, poderá ver dois events Criados gerados, mesmo que apenas um único arquivo tenha sido criado. Isso ocorre porque o Notepad executa várias ações do sistema de arquivos durante o processo de gravação. O bloco de notas grava no disco em lotes que criam o conteúdo do arquivo e, em seguida, os atributos do arquivo. Outros aplicativos podem executar da mesma maneira. Como o FileSystemWatcher monitora as atividades do sistema operacional, todos os events que esses aplicativos acionam serão selecionados.

    Agora, este bit de texto é sobre o evento Created , mas a mesma coisa se aplica a outros events de arquivo também. Em alguns aplicativos, você pode conseguir contornar isso usando a propriedade NotifyFilter , mas minha experiência diz que às vezes você também precisa fazer alguns filtros manuais duplicados (hacks).

    Um tempo atrás eu marquei uma página com algumas dicas do FileSystemWatcher . Você pode querer dar uma olhada.

    Eu “consertei” esse problema usando a seguinte estratégia no meu delegado:

     // fsw_ is the FileSystemWatcher instance used by my application. private void OnDirectoryChanged(...) { try { fsw_.EnableRaisingEvents = false; /* do my stuff once asynchronously */ } finally { fsw_.EnableRaisingEvents = true; } } 

    Quaisquer events OnChanged duplicados do FileSystemWatcher podem ser detectados e descartados, marcando-se o File.GetLastWriteTime data File.GetLastWriteTime hora File.GetLastWriteTime no arquivo em questão. Igual a:

     DateTime lastRead = DateTime.MinValue; void OnChanged(object source, FileSystemEventArgs a) { DateTime lastWriteTime = File.GetLastWriteTime(uri); if (lastWriteTime != lastRead) { doStuff(); lastRead = lastWriteTime; } // else discard the (duplicated) OnChanged event } 

    Aqui está a minha solução que me ajudou a parar o evento sendo levantado duas vezes:

     watcher.NotifyFilter = NotifyFilters.FileName | NotifyFilters.Size; 

    Aqui eu defini a propriedade NotifyFilter com apenas nome de arquivo e tamanho.
    watcher é o meu object de FileSystemWatcher. Espero que isso ajude.

    Meu cenário é que eu tenho uma máquina virtual com um servidor Linux nele. Estou desenvolvendo arquivos no host do Windows. Quando eu mudo alguma coisa em uma pasta no host, eu quero que todas as alterações sejam enviadas, sincronizadas no servidor virtual via Ftp. É assim que elimino o evento de alteração duplicado quando escrevo em um arquivo (que também marca a pasta que contém o arquivo a ser modificado):

     private Hashtable fileWriteTime = new Hashtable(); private void fsw_sync_Changed(object source, FileSystemEventArgs e) { string path = e.FullPath.ToString(); string currentLastWriteTime = File.GetLastWriteTime( e.FullPath ).ToString(); // if there is no path info stored yet // or stored path has different time of write then the one now is inspected if ( !fileWriteTime.ContainsKey(path) || fileWriteTime[path].ToString() != currentLastWriteTime ) { //then we do the main thing log( "A CHANGE has occured with " + path ); //lastly we update the last write time in the hashtable fileWriteTime[path] = currentLastWriteTime; } } 

    Principalmente eu crio uma hashtable para armazenar informações de tempo de gravação de arquivos. Então, se a hashtable tiver o caminho de arquivo que é modificado e seu valor de tempo for o mesmo que a alteração do arquivo notificado no momento, sei que é a duplicata do evento e a ignoro.

    Aqui está minha abordagem:

     // Consider having a List named _changedFiles private void OnChanged(object source, FileSystemEventArgs e) { lock (_changedFiles) { if (_changedFiles.Contains(e.FullPath)) { return; } _changedFiles.Add(e.FullPath); } // do your stuff System.Timers.Timer timer = new Timer(1000) { AutoReset = false }; timer.Elapsed += (timerElapsedSender, timerElapsedArgs) => { lock (_changedFiles) { _changedFiles.Remove(e.FullPath); } }; timer.Start(); } 

    Esta é a solução que usei para resolver esse problema em um projeto no qual enviava o arquivo como anexo por email. Ele evitará facilmente o evento duas vezes acionado, mesmo com um intervalo de timer menor, mas no meu caso, 1000 foi bom, já que fiquei mais feliz com a falta de algumas alterações do que com inundar a checkbox de correio com mais de uma mensagem por segundo. Pelo menos funciona bem no caso de vários arquivos serem alterados ao mesmo tempo.

    Outra solução que pensei seria replace a lista por um arquivo de mapeamento de dictionary para seu respectivo MD5, assim você não teria que escolher um intervalo arbitrário, já que você não teria que excluir a input, mas atualizar seu valor, e cancele suas coisas se não mudou. Ele tem o lado negativo de ter um dictionary crescendo na memory enquanto os arquivos são monitorados e comendo mais e mais memory, mas eu li em algum lugar que a quantidade de arquivos monitorados depende do buffer interno do FSW, então talvez não tão crítico. Não sei como o tempo de computação do MD5 afetaria o desempenho do seu código também, cuidado = \

    Tente com este código:

     class WatchPlotDirectory { bool let = false; FileSystemWatcher watcher; string path = "C:/Users/jamie/OneDrive/Pictures/Screenshots"; public WatchPlotDirectory() { watcher = new FileSystemWatcher(); watcher.Path = path; watcher.NotifyFilter = NotifyFilters.LastAccess | NotifyFilters.LastWrite | NotifyFilters.FileName | NotifyFilters.DirectoryName; watcher.Filter = "*.*"; watcher.Changed += new FileSystemEventHandler(OnChanged); watcher.Renamed += new RenamedEventHandler(OnRenamed); watcher.EnableRaisingEvents = true; } void OnChanged(object sender, FileSystemEventArgs e) { if (let==false) { string mgs = string.Format("File {0} | {1}", e.FullPath, e.ChangeType); Console.WriteLine("onchange: " + mgs); let = true; } else { let = false; } } void OnRenamed(object sender, RenamedEventArgs e) { string log = string.Format("{0} | Renamed from {1}", e.FullPath, e.OldName); Console.WriteLine("onrenamed: " + log); } public void setPath(string path) { this.path = path; } } 

    Eu sei que este é um problema antigo, mas tinha o mesmo problema e nenhuma das soluções acima realmente fez o truque para o problema que eu estava enfrentando. Eu criei um dictionary que mapeia o nome do arquivo com o LastWriteTime. Então, se o arquivo não está no dictionary, vá em frente com o processo, caso contrário, verifique para ver quando foi a última vez modificada e se é diferente do que é no dictionary executar o código.

      Dictionary dateTimeDictionary = new Dictionary(); private void OnChanged(object source, FileSystemEventArgs e) { if (!dateTimeDictionary.ContainsKey(e.FullPath) || (dateTimeDictionary.ContainsKey(e.FullPath) && System.IO.File.GetLastWriteTime(e.FullPath) != dateTimeDictionary[e.FullPath])) { dateTimeDictionary[e.FullPath] = System.IO.File.GetLastWriteTime(e.FullPath); //your code here } } 

    Aqui está uma nova solução que você pode tentar. Funciona bem para mim. No manipulador de events para o evento alterado programaticamente, remova o manipulador da saída do designer uma mensagem, se desejado, em seguida, adicione programaticamente o manipulador de volta. exemplo:

     public void fileSystemWatcher1_Changed( object sender, System.IO.FileSystemEventArgs e ) { fileSystemWatcher1.Changed -= new System.IO.FileSystemEventHandler( fileSystemWatcher1_Changed ); MessageBox.Show( "File has been uploaded to destination", "Success!" ); fileSystemWatcher1.Changed += new System.IO.FileSystemEventHandler( fileSystemWatcher1_Changed ); } 

    Um possível ‘hack’ seria controlar os events usando Extensões Reativas, por exemplo:

     var watcher = new FileSystemWatcher("./"); Observable.FromEventPattern(watcher, "Changed") .Throttle(new TimeSpan(500000)) .Subscribe(HandleChangeEvent); watcher.EnableRaisingEvents = true; 

    Nesse caso, estou acelerando para 50 ms, no meu sistema isso foi o suficiente, mas valores mais altos devem ser mais seguros. (E como eu disse, ainda é um ‘hack’).

    A principal razão foi a hora do último access do primeiro evento ser a hora atual (gravação do arquivo ou hora alterada). o segundo evento foi o último access original do arquivo. Eu resolvo sob código.

      var lastRead = DateTime.MinValue; Watcher = new FileSystemWatcher(...) { NotifyFilter = NotifyFilters.FileName | NotifyFilters.LastWrite, Filter = "*.dll", IncludeSubdirectories = false, }; Watcher.Changed += (senderObject, ea) => { var now = DateTime.Now; var lastWriteTime = File.GetLastWriteTime(ea.FullPath); if (now == lastWriteTime) { return; } if (lastWriteTime != lastRead) { // do something... lastRead = lastWriteTime; } }; Watcher.EnableRaisingEvents = true; 

    Passei uma quantidade significativa de tempo usando o FileSystemWatcher, e algumas das abordagens aqui não funcionarão. Eu realmente gostei da abordagem de events de desativação, mas infelizmente, não funciona se houver> 1 arquivo sendo descartado, o segundo arquivo será perdido a maioria, senão todas as vezes. Então eu uso a seguinte abordagem:

     private void EventCallback(object sender, FileSystemEventArgs e) { var fileName = e.FullPath; if (!File.Exists(fileName)) { // We've dealt with the file, this is just supressing further events. return; } // File exists, so move it to a working directory. File.Move(fileName, [working directory]); // Kick-off whatever processing is required. } 

    Eu tenho uma solução muito rápida e simples aqui, funciona para mim, e não importa o evento seria acionado uma ou duas vezes ou mais vezes, ocasionalmente, confira:

     private int fireCount = 0; private void inputFileWatcher_Changed(object sender, FileSystemEventArgs e) { fireCount++; if (fireCount == 1) { MessageBox.Show("Fired only once!!"); dowork(); } else { fireCount = 0; } } } 

    Este código funcionou para mim.

      private void OnChanged(object source, FileSystemEventArgs e) { string fullFilePath = e.FullPath.ToString(); string fullURL = buildTheUrlFromStudyXML(fullFilePath); System.Diagnostics.Process.Start("iexplore", fullURL); Timer timer = new Timer(); ((FileSystemWatcher)source).Changed -= new FileSystemEventHandler(OnChanged); timer.Interval = 1000; timer.Elapsed += new ElapsedEventHandler(t_Elapsed); timer.Start(); } private void t_Elapsed(object sender, ElapsedEventArgs e) { ((Timer)sender).Stop(); theWatcher.Changed += new FileSystemEventHandler(OnChanged); } 

    principalmente para o futuro eu 🙂

    Eu escrevi um wrapper usando Rx:

      public class WatcherWrapper : IDisposable { private readonly FileSystemWatcher _fileWatcher; private readonly Subject _infoSubject; private Subject _eventSubject; public WatcherWrapper(string path, string nameFilter = "*.*", NotifyFilters? notifyFilters = null) { _fileWatcher = new FileSystemWatcher(path, nameFilter); if (notifyFilters != null) { _fileWatcher.NotifyFilter = notifyFilters.Value; } _infoSubject = new Subject(); _eventSubject = new Subject(); Observable.FromEventPattern(_fileWatcher, "Changed").Select(e => e.EventArgs) .Subscribe(_infoSubject.OnNext); Observable.FromEventPattern(_fileWatcher, "Created").Select(e => e.EventArgs) .Subscribe(_infoSubject.OnNext); Observable.FromEventPattern(_fileWatcher, "Deleted").Select(e => e.EventArgs) .Subscribe(_infoSubject.OnNext); Observable.FromEventPattern(_fileWatcher, "Renamed").Select(e => e.EventArgs) .Subscribe(_infoSubject.OnNext); // this takes care of double events and still works with changing the name of the same file after a while _infoSubject.Buffer(TimeSpan.FromMilliseconds(20)) .Select(x => x.GroupBy(z => z.FullPath).Select(z => z.LastOrDefault()).Subscribe( infos => { if (infos != null) foreach (var info in infos) { { _eventSubject.OnNext(info); } } }); _fileWatcher.EnableRaisingEvents = true; } public IObservable FileEvents => _eventSubject; public void Dispose() { _fileWatcher?.Dispose(); _eventSubject.Dispose(); _infoSubject.Dispose(); } } 

    Uso:

     var watcher = new WatcherWrapper(_path, "*.info"); // all more complicated and scenario specific filtering of events can be done here watcher.FileEvents.Where(x => x.ChangeType != WatcherChangeTypes.Deleted).Subscribe(x => //do stuff) 

    Eu mudei a maneira de monitorar arquivos em diretórios. Em vez de usar o FileSystemWatcher, pesquise locais em outro thread e, em seguida, examine o LastWriteTime do arquivo.

     DateTime lastWriteTime = File.GetLastWriteTime(someFilePath); 

    Usando essas informações e mantendo um índice de um caminho de arquivo e seu tempo de gravação mais recente, posso determinar arquivos que foram alterados ou que foram criados em um determinado local. Isso me remove das esquisitices do FileSystemWatcher. A principal desvantagem é que você precisa de uma estrutura de dados para armazenar o LastWriteTime e a referência ao arquivo, mas é confiável e fácil de implementar.

    Você pode tentar abri-lo para gravação e, se for bem-sucedido, poderá assumir que o outro aplicativo é feito com o arquivo.

     private void OnChanged(object source, FileSystemEventArgs e) { try { using (var fs = File.OpenWrite(e.FullPath)) { } //do your stuff } catch (Exception) { //no write access, other app not done } } 

    Apenas abri-lo para gravação parece não levantar o evento alterado. Então deve ser seguro.

    Desculpem a escavação grave, mas eu tenho lutado contra esse problema há algum tempo e finalmente encontrei uma forma de lidar com esses events múltiplos. Gostaria de agradecer a todos neste tópico, pois usei-o em muitas referências ao combater esse problema.

    Aqui está o meu código completo. Ele usa um dictionary para rastrear a data e a hora da última gravação do arquivo. Ele compara esse valor e, se for o mesmo, suprime os events. Em seguida, define o valor depois de iniciar o novo segmento.

     using System.Threading; // used for backgroundworker using System.Diagnostics; // used for file information private static IDictionary fileModifiedTable = new Dictionary(); // used to keep track of our changed events private void fswFileWatch_Changed( object sender, FileSystemEventArgs e ) { try { //check if we already have this value in our dictionary. if ( fileModifiedTable.TryGetValue( e.FullPath, out sEmpty ) ) { //compare timestamps if ( fileModifiedTable[ e.FullPath ] != File.GetLastWriteTime( e.FullPath ).ToString() ) { //lock the table lock ( fileModifiedTable ) { //make sure our file is still valid if ( File.Exists( e.FullPath ) ) { // create a new background worker to do our task while the main thread stays awake. Also give it do work and work completed handlers BackgroundWorker newThreadWork = new BackgroundWorker(); newThreadWork.DoWork += new DoWorkEventHandler( bgwNewThread_DoWork ); newThreadWork.RunWorkerCompleted += new RunWorkerCompletedEventHandler( bgwNewThread_RunWorkerCompleted ); // capture the path string eventFilePath = e.FullPath; List arguments = new List(); // add arguments to pass to the background worker arguments.Add( eventFilePath ); arguments.Add( newEvent.File_Modified ); // start the new thread with the arguments newThreadWork.RunWorkerAsync( arguments ); fileModifiedTable[ e.FullPath ] = File.GetLastWriteTime( e.FullPath ).ToString(); //update the modified table with the new timestamp of the file. FILE_MODIFIED_FLAG.WaitOne(); // wait for the modified thread to complete before firing the next thread in the event multiple threads are being worked on. } } } } } catch ( IOException IOExcept ) { //catch any errors postError( IOExcept, "fswFileWatch_Changed" ); } } 

    Eu criei um repository do Git com uma class que estende o FileSystemWatcher para acionar os events somente quando a cópia é feita. Ele descarta todos os events alterados, exceto o último, e o lança apenas quando o arquivo se torna disponível para leitura.

    Faça o download do FileSystemSafeWatcher e adicione-o ao seu projeto.

    Em seguida, use-o como um FileSystemWatcher normal e monitore quando os events forem acionados.

     var fsw = new FileSystemSafeWatcher(file); fsw.EnableRaisingEvents = true; // Add event handlers here fsw.Created += fsw_Created; 

    Consegui fazer isso adicionando uma function que verifica as duplicatas em uma matriz de buffer.

    Em seguida, execute a ação após o array não ter sido modificado para o X time usando um timer: – Reinicialize o timer toda vez que algo for gravado no buffer – Execute a ação no tick

    Isso também captura outro tipo de duplicação. Se você modificar um arquivo dentro de uma pasta, a pasta também lançará um evento Change.

     Function is_duplicate(str1 As String) As Boolean If lb_actions_list.Items.Count = 0 Then Return False Else Dim compStr As String = lb_actions_list.Items(lb_actions_list.Items.Count - 1).ToString compStr = compStr.Substring(compStr.IndexOf("-") + 1).Trim If compStr <> str1 AndAlso compStr.parentDir <> str1 & "\" Then Return False Else Return True End If End If End Function Public Module extentions  Public Function parentDir(ByVal aString As String) As String Return aString.Substring(0, CInt(InStrRev(aString, "\", aString.Length - 1))) End Function End Module 
     FileReadTime = DateTime.Now; private void File_Changed(object sender, FileSystemEventArgs e) { var lastWriteTime = File.GetLastWriteTime(e.FullPath); if (lastWriteTime.Subtract(FileReadTime).Ticks > 0) { // code FileReadTime = DateTime.Now; } } 

    Esta solução funcionou para mim na aplicação de produção:

    Meio Ambiente:

    VB.Net Framework 4.5.2

    Definir propriedades de object manualmente: NotifyFilter = Size

    Então use este código:

     Public Class main Dim CalledOnce = False Private Sub FileSystemWatcher1_Changed(sender As Object, e As IO.FileSystemEventArgs) Handles FileSystemWatcher1.Changed If (CalledOnce = False) Then CalledOnce = True If (e.ChangeType = 4) Then ' Do task... CalledOnce = False End If End Sub End Sub 

    Tente isso!

     string temp=""; public void Initialize() { FileSystemWatcher _fileWatcher = new FileSystemWatcher(); _fileWatcher.Path = "C:\\Folder"; _fileWatcher.NotifyFilter = NotifyFilters.LastWrite; _fileWatcher.Filter = "Version.txt"; _fileWatcher.Changed += new FileSystemEventHandler(OnChanged); _fileWatcher.EnableRaisingEvents = true; } private void OnChanged(object source, FileSystemEventArgs e) { ....... if(temp=="") { //do thing you want. temp = e.name //name of text file. }else if(temp !="" && temp != e.name) { //do thing you want. temp = e.name //name of text file. }else { //second fire ignored. } } 

    Eu tive que combinar várias idéias das postagens acima e adicionar verificação de bloqueio de arquivo para que funcionasse para mim:

     FileSystemWatcher fileSystemWatcher; private void DirectoryWatcher_Start() { FileSystemWatcher fileSystemWatcher = new FileSystemWatcher { Path = @"c:\mypath", NotifyFilter = NotifyFilters.LastWrite, Filter = "*.*", EnableRaisingEvents = true }; fileSystemWatcher.Changed += new FileSystemEventHandler(DirectoryWatcher_OnChanged); } private static void WaitUntilFileIsUnlocked(String fullPath, Action callback, FileAccess fileAccess = FileAccess.Read, Int32 timeoutMS = 10000) { Int32 waitMS = 250; Int32 currentMS = 0; FileInfo file = new FileInfo(fullPath); FileStream stream = null; do { try { stream = file.Open(FileMode.Open, fileAccess, FileShare.None); stream.Close(); callback(fullPath); return; } catch (IOException) { } finally { if (stream != null) stream.Dispose(); } Thread.Sleep(waitMS); currentMS += waitMS; } while (currentMS < timeoutMS); } private static Dictionary DirectoryWatcher_fileLastWriteTimeCache = new Dictionary(); private void DirectoryWatcher_OnChanged(Object source, FileSystemEventArgs ev) { try { lock (DirectoryWatcher_fileLastWriteTimeCache) { DateTime lastWriteTime = File.GetLastWriteTime(ev.FullPath); if (DirectoryWatcher_fileLastWriteTimeCache.ContainsKey(ev.FullPath)) { if (DirectoryWatcher_fileLastWriteTimeCache[ev.FullPath].AddMilliseconds(500) >= lastWriteTime) return; // file was already handled } DirectoryWatcher_fileLastWriteTimeCache[ev.FullPath] = lastWriteTime; } Task.Run(() => WaitUntilFileIsUnlocked(ev.FullPath, fullPath => { // do the job with fullPath... })); } catch (Exception e) { // handle exception } } 

    Event if not asked, it is a shame there are no ready solution samples for F#. To fix this here is my recipe, just because I can and F# is a wonderful .NET language.

    Duplicated events are filtered out using FSharp.Control.Reactive package, which is just a F# wrapper for reactive extensions. All that can be targeted to full framework or netstandard2.0 :

     let createWatcher path filter () = new FileSystemWatcher( Path = path, Filter = filter, EnableRaisingEvents = true, SynchronizingObject = null // not needed for console applications ) let createSources (fsWatcher: FileSystemWatcher) = // use here needed events only. // convert `Error` and `Renamed` events to be merded [| fsWatcher.Changed :> IObservable<_> fsWatcher.Deleted :> IObservable<_> fsWatcher.Created :> IObservable<_> //fsWatcher.Renamed |> Observable.map renamedToNeeded //fsWatcher.Error |> Observable.map errorToNeeded |] |> Observable.mergeArray let handle (e: FileSystemEventArgs) = printfn "handle %A event '%s' '%s' " e.ChangeType e.Name e.FullPath let watch path filter throttleTime = // disposes watcher if observer subscription is disposed Observable.using (createWatcher path filter) createSources // filter out multiple equal events |> Observable.distinctUntilChanged // filter out multiple Changed |> Observable.throttle throttleTime |> Observable.subscribe handle [] let main _args = let path = @"C:\Temp\WatchDir" let filter = "*.zip" let throttleTime = TimeSpan.FromSeconds 10. use _subscription = watch path filter throttleTime System.Console.ReadKey() |> ignore 0 // return an integer exit code 

    I approached the double create issue like this, which ignores the first event:

     Private WithEvents fsw As New System.IO.FileSystemWatcher Private complete As New List(Of String) Private Sub fsw_Created(ByVal sender As Object, _ ByVal e As System.IO.FileSystemEventArgs) Handles fsw.Created If Not complete.Contains(e.FullPath) Then complete.Add(e.FullPath) Else complete.Remove(e.FullPath) Dim th As New Threading.Thread(AddressOf hprocess) th.Start(e) End If End Sub 

    Alot of these answers are shocking, really. Heres some code from my XanderUI Control library that fixes this.

     private void OnChanged(object sender, FilesystemEventArgs e) { if (FSWatcher.IncludeSubdirectories == true) { if (File.Exists(e.FullPath)) { DO YOUR FILE CHANGE STUFF HERE... } } else DO YOUR DIRECTORY CHANGE STUFF HERE... } 

    if you register to the OnChanged event, then by deleting the monitored file before changing it might work, as long as you only need to monitor the OnChange event..

    Make it simple define one global variable var1 = true .

     Private Sub FileWatchman_Changed(ByVal sender As System.Object, ByVal e As System.IO.FileSystemEventArgs) Handles FileWatchman.Changed If var1 = true your logic goes here var1 = false Else var1 = true End If End Sub 

    Well, here is my solution how to raise an event only once:

     FileSystemWatcheк watcher = new FileSystemWatcher(); //'path' - path to the file that has been modified. watcher.Changed += (s, e) => FileChanged(path); 

    here is implementation of FileChanged

     //count is our counter to triger when we can raise and when not. private int count = 0; private void FileChanged(string path) { if (count % 2 == 0) { //code here } count ++; }