FileSystemWatcher vs polling untuk melihat perubahan file


152

Saya perlu mengatur aplikasi yang mengawasi file yang dibuat dalam direktori, baik secara lokal maupun pada drive jaringan.

Apakah FileSystemWatcheratau polling pada timer akan menjadi pilihan terbaik. Saya telah menggunakan kedua metode di masa lalu, tetapi tidak secara ekstensif.

Masalah apa (kinerja, keandalan, dll.) Yang ada pada kedua metode tersebut?


3
FileSystemWatcher adalah abstraksi yang bocor dan tidak dapat diandalkan untuk apa pun kecuali kasus yang paling mendasar. Lihat di sini: stackoverflow.com/a/22768610/129130
Stein Åsmul

1
Ingin menambahkan tautan untuk referensi ke jawaban ini oleh Raymond Chen (pakar Microsoft) tentang topik keandalan FileSystemWatcher . Dan blog-nya: The Old New Thing (mencari FileSystemWatcher misalnya).
Stein Åsmul

Jawaban:


105

Saya telah melihat pengamat sistem file gagal dalam lingkungan produksi dan pengujian. Saya sekarang menganggapnya sebagai kenyamanan, tetapi saya tidak menganggapnya dapat diandalkan. Pola saya adalah untuk melihat perubahan dengan pengamat sistem file, tetapi jajak pendapat sesekali untuk menangkap perubahan file yang hilang.

Sunting: Jika Anda memiliki UI, Anda juga dapat memberi pengguna Anda kemampuan untuk "menyegarkan" untuk perubahan daripada polling. Saya akan menggabungkan ini dengan pengamat sistem file.


11
Saya telah melihat jika jatuh juga. Solusi yang kami gunakan adalah untuk membungkus kelas kami sendiri, di mana kelas pembungkus JUGA menggunakan timer untuk memeriksa jika pengamat masih pergi.
Joel Coehoorn

Kami melakukan hal serupa - setelah kami memproses file masuk ke acara FileCreated, kami melakukan pemeriksaan manual untuk file baru lainnya sebelum kembali. Ini tampaknya mengurangi masalah yang terjadi dengan banyak file yang tiba sekaligus.
John Sibly

4
Saya percaya kami mengujinya di XP dan Server 2003 pada direktori lokal dan berbagi file, dan memiliki mesin XP di lapangan. Kami memiliki masalah dengan direktori lokal dan berbagi file. Salah satu kemungkinan penyebab yang kami temukan adalah salinan / pembuatan banyak file dalam waktu singkat di direktori.
Jason Jackson

5
Tidaklah konstruktif dan profesional untuk menyatakan "aku pernah melihat hantu suatu hari". Tampaknya orang-orang di ujung tanduk, menyebutkan dokumen msdn tentang overruns buffer non-halaman-outable dapat menjelaskan masalah Anda. Sudahkah Anda mencoba menggunakan pendekatan Brent?
v.oddou

4
Saya baru saja membeli sensor gas di Amazon dan membuat saya takjub betapa banyak orang mengatakan itu tidak berfungsi, ketika mereka jelas tidak mengkalibrasi dengan benar atau bahkan tidak tahu tentang kalibrasi ... FileSystemWatcher telah mengetahui keterbatasan dengan lalu lintas tinggi dari ukuran buffer-nya. Hampir dijamin itulah alasannya "gagal". Ini mudah dijelaskan dalam dokumentasi dan ada pekerjaan di sekitar yang menyediakan operasi yang sangat andal (seperti yang diposting di bawah). Ini bukan jawaban yang baik untuk hanya mengatakan "errr, sesuatu tidak berhasil pada suatu waktu, tidak yakin mengapa ... tidak ada yang harus bergantung padanya".
u8it

60

Masalah terbesar yang saya miliki adalah file yang hilang ketika buffer sudah penuh. Mudah dipecahkan - cukup tambahkan buffer. Ingat bahwa itu berisi nama file dan peristiwa, jadi tingkatkan ke jumlah file yang diharapkan (coba-coba). Itu memang menggunakan memori yang tidak dapat dihubungi, sehingga bisa memaksa proses lain ke halaman jika memori semakin rendah.

Berikut ini adalah artikel MSDN pada buffer: FileSystemWatcher .. :: .InternBufferSize Property

Per MSDN:

Meningkatkan ukuran buffer mahal, karena berasal dari memori non-paged yang tidak dapat ditukar ke disk, jadi jaga buffer sekecil mungkin. Untuk menghindari buffer overflow, gunakan properti NotifyFilter dan IncludeSubdirectories untuk menyaring pemberitahuan perubahan yang tidak diinginkan.

Kami menggunakan 16MB karena batch besar diharapkan pada satu waktu. Berfungsi dengan baik dan tidak pernah melewatkan file.

Kami juga membaca semua file sebelum mulai memproses bahkan satu ... dapatkan nama file dengan aman di-cache (dalam kasus kami, ke dalam tabel database) kemudian memprosesnya.

Untuk masalah penguncian file, saya menelurkan proses yang menunggu file dibuka kuncinya menunggu satu detik, kemudian dua, kemudian empat, dan sebagainya. Kami tidak pernah polling. Ini telah diproduksi tanpa kesalahan selama sekitar dua tahun.


12
Buffer overflow? Oh, maksud Anda stack overflow.
TheFlash

1
Pada 3.5. NET: "Anda dapat mengatur buffer ke 4 KB atau lebih besar, tetapi tidak boleh melebihi 64 KB"
brad

9
Bagaimana Anda menggunakan 16MB jika buffer internal maksimal untuk FileSystemWatcher adalah 64KB?
BK

1
@ Jarvis, buffer adalah lokasi penyimpanan temperary yang dikonfigurasikan untuk menyimpan informasi saat ditransmisikan hingga dapat diproses, ini biasanya berarti FIFO atau Antrian karena Anda ingin menangani permintaan dalam urutan kedatangannya namun dalam beberapa proses seperti rekursi dalam program struktur FILO atau Stack adalah apa yang digunakan, Dalam hal ini kita pasti mengacu pada buffer acara antrian dan bukan program yang memanggil stack buffer
MikeT

1
petermeinl.wordpress.com/2015/05/18/tamed-filesystemwatcher Posting ini membagikan pembungkus yang kuat di sekitar FileSystemWatcher (FSW) memperbaiki masalah standar yang biasa dihadapi saat menggunakannya untuk memantau sistem file dalam aplikasi dunia nyata.
Kiquenet

35

The FileSystemWatcherjuga mungkin kehilangan perubahan selama sibuk kali, jika jumlah perubahan antri meluap buffer disediakan. Ini bukan batasan dari kelas .NET per se, tetapi dari infrastruktur Win32 yang mendasarinya. Dalam pengalaman kami, cara terbaik untuk meminimalkan masalah ini adalah dengan membagikan pemberitahuan secepat mungkin dan menghadapinya di utas lainnya.

Seperti disebutkan oleh @ChillTemp di atas, pengamat tidak dapat bekerja pada saham non-Windows. Misalnya, itu tidak akan berfungsi sama sekali pada drive Novell yang terpasang.

Saya setuju bahwa kompromi yang baik adalah melakukan jajak pendapat sesekali untuk mengambil setiap perubahan yang terlewat.


4
Pengamat filesystem dapat mulai memunculkan banyak acara secara berurutan. Jika Anda tidak dapat mengeksekusi event handler Anda setidaknya secepat mereka dipecat, akhirnya handler akan mulai menjatuhkan acara di lantai dan Anda akan kehilangan beberapa hal.
Brent Rockwood

17

Perhatikan juga bahwa pengamat sistem file tidak dapat diandalkan pada berbagi file. Terutama jika berbagi file di-host di server non-windows. FSW tidak boleh digunakan untuk hal-hal penting. Atau harus digunakan dengan jajak pendapat sesekali untuk memverifikasi bahwa ia tidak melewatkan apa pun.


3
Sudahkah Microsoft mengakui bahwa itu tidak dapat diandalkan pada berbagi file non-windows? Kami tentu saja mengalami tangan pertama ini sejak beralih dari share Windows ke share SMB berbasis Linux.
Sean

1
Bukannya aku sadar. Dan saya yakin itu hanya akan menjadi permainan menyalahkan antara vendor yang berbeda.
chilltemp

1
Kami mengalami masalah dengan pengamat sistem file pada drive yang dipetakan. Jika peta terputus dan kemudian menghubungkan kembali pengamat file tidak lagi menimbulkan perubahan. Mudah diatasi tetapi masih mogok terhadap pengamat sistem file IMHO.
Richard Dorman

11

Secara pribadi, saya telah menggunakan FileSystemWatchersistem produksi, dan sudah bekerja dengan baik. Dalam 6 bulan terakhir, itu tidak memiliki cegukan tunggal berjalan 24x7. Ini memantau folder lokal tunggal (yang dibagikan). Kami memiliki sejumlah kecil operasi file yang harus ditangani (10 peristiwa dipecat per hari). Itu bukan sesuatu yang pernah saya khawatirkan. Saya akan menggunakannya lagi jika saya harus membuat kembali keputusan.


7

Saat ini saya menggunakan FileSystemWatcherpada file XML yang diperbarui rata-rata setiap 100 milidetik.

Saya telah menemukan bahwa selama FileSystemWatcherdikonfigurasi dengan benar Anda seharusnya tidak pernah memiliki masalah dengan file lokal .

Saya tidak punya pengalaman tentang menonton file jarak jauh dan berbagi non-Windows.

Saya akan mempertimbangkan polling file menjadi berlebihan dan tidak sebanding dengan biaya overhead kecuali Anda secara inheren tidak mempercayai FileSystemWatcheratau secara langsung mengalami keterbatasan semua orang di sini telah terdaftar (saham non-Windows, dan menonton file jarak jauh).


5

Saya akan pergi dengan polling.

Masalah jaringan menyebabkan FileSystemWatchertidak dapat diandalkan (bahkan ketika overloading peristiwa kesalahan).


5

Saya mengalami masalah saat menggunakan FileSystemWatcherberbagi jaringan. Jika Anda berada di lingkungan Windows murni, itu mungkin tidak menjadi masalah, tapi saya menonton berbagi NFS dan karena NFS tidak memiliki kewarganegaraan, tidak pernah ada pemberitahuan ketika file yang saya tonton berubah.


Saya telah menemukan masalah yang sama, tetapi tidak terduga bagi saya karena FileSystemWatcher berada di server windows yang sama yang berbagi folder menggunakan NFS. fakta berbagi folder dengan NFS menyebabkan filesystemwatcher tidak melihat file yang dibuat menggunakan share dari jarak jauh (yaitu dari Linux yang memetakan share) sementara jika saya menulis file pada folder yang sama di bawah pemantauan, filesystemwatcher dipicu. sepertinya server NFS menulis file menggunakan lapisan yang lebih rendah dan lapisan api yang memicu filesystemwatcher tidak terlibat, ada yang punya info lebih lanjut?
Mosè Bottacini

3

Saya punya beberapa masalah besar dengan FSW pada drive jaringan: Menghapus file selalu melempar kesalahan, tidak pernah menghapus kejadian. Saya tidak menemukan solusi, jadi saya sekarang menghindari FSW dan menggunakan polling.

Acara penciptaan di sisi lain bekerja dengan baik, jadi jika Anda hanya perlu melihat pembuatan file, Anda dapat menggunakan FSW.

Juga, saya tidak punya masalah sama sekali pada folder lokal, tidak masalah apakah dibagikan atau tidak.


3

Kembali dari metode acara secepat mungkin, menggunakan utas lain, menyelesaikan masalah untuk saya:

private void Watcher_Created(object sender, FileSystemEventArgs e)
{
    Task.Run(() => MySubmit(e.FullPath));
}

2

Menggunakan FSW dan polling adalah pemborosan waktu dan sumber daya, menurut pendapat saya, dan saya terkejut bahwa pengembang yang berpengalaman menyarankannya. Jika Anda perlu menggunakan polling untuk memeriksa "ada kesalahan FSW", maka Anda dapat, secara alami, membuang FSW sama sekali dan hanya menggunakan polling.

Saya, saat ini, mencoba untuk memutuskan apakah saya akan menggunakan FSW atau polling untuk proyek yang saya kembangkan. Membaca jawabannya, jelas bahwa ada kasus di mana FSW memenuhi kebutuhan dengan sempurna, sementara di lain waktu, Anda perlu polling. Sayangnya, tidak ada jawaban yang benar-benar berurusan dengan perbedaan kinerja (jika ada), hanya dengan masalah "keandalan". Adakah orang yang bisa menjawab bagian pertanyaan itu?

EDIT: nmclean untuk validitas menggunakan FSW dan polling (Anda dapat membaca diskusi di komentar, jika Anda tertarik) tampaknya menjadi penjelasan yang sangat rasional mengapa mungkin ada situasi yang menggunakan FSW dan polling adalah efisien. Terima kasih telah menjelaskan hal itu untuk saya (dan siapa pun yang memiliki pendapat yang sama), nmclean .


1
Bagaimana jika Anda ingin merespons perubahan file secepat mungkin? Misalnya, jika Anda melakukan polling satu kali per menit, Anda mungkin memiliki penundaan 1 menit antara pengubahan file dan aplikasi Anda mengambil perubahan. Acara FSW mungkin akan dipicu jauh sebelum itu. Jadi dengan menggunakan keduanya Anda menangani acara dengan sesedikit mungkin, tetapi juga mengambil acara yang terlewatkan jika ada.
rom99

@ rom99 Persis saya. Jika FSW tidak dapat diandalkan dalam kasus Anda memerlukan respons cepat, tidak ada gunanya menggunakannya, karena Anda akan memiliki kasus di mana tidak akan ada respons cepat, dengan demikian, aplikasi Anda akan tidak dapat diandalkan. Polling dalam interval yang lebih pendek, di utas, akan menjadi apa yang perlu Anda lakukan. Dengan melakukan keduanya , berarti Anda memiliki toleransi dalam waktu respons yang disediakan oleh polling, jadi, mengapa tidak menggunakan polling saja?
ThunderGr

5
@ThunderGr "dengan demikian, aplikasi Anda tidak dapat diandalkan." - Dalam banyak kasus, kecepatan bukanlah prasyarat untuk keandalan. Pekerjaan harus diselesaikan, tetapi bisa menunggu beberapa saat. Jika kami menggabungkan polling lambat, andal dengan FSW cepat, tidak dapat diandalkan , kami mendapatkan aplikasi yang selalu andal dan terkadang cepat, yang lebih baik daripada andal dan tidak pernah cepat. Kami dapat menghapus FSW dan mencapai waktu respons maksimum yang sama dengan melakukan pemungutan suara konstan, tetapi ini dengan mengorbankan respon dari sisa aplikasi, jadi hanya boleh dilakukan jika respons segera benar-benar diperlukan.
nmclean

2
Sekarang mengapa argumen di atas buruk? Karena, walaupun kita masih membutuhkan akses disk, kita membutuhkannya lebih sedikit . Demikian pula, Anda dapat polling lebih sedikit. Hanya karena kami masih memeriksa semua file tidak berarti beban kerjanya sama. Pernyataan Anda, "polling mahal pada waktu CPU dengan FSW atau tidak," salah . Dengan membongkar perhatian "kedekatan" ke FSW, kita dapat mengubah pemungutan suara menjadi tugas yang menganggur, dengan prioritas rendah, sehingga kesibukan aplikasi pada waktu tertentu berkurang secara drastis sambil tetap memberikan "suguhan" kedekatan. Anda tidak bisa mencapai keseimbangan yang sama dengan polling saja.
nmclean

9
@nmclean Terima kasih telah meluangkan waktu dan energi untuk mengklarifikasi ini seperti yang Anda lakukan. Ketika Anda mengatakannya seperti itu, itu pasti jauh lebih masuk akal. Sama seperti ada saat-saat cache tidak cocok untuk masalah spesifik Anda, sehingga FSW (ketika terbukti tidak dapat diandalkan) mungkin tidak cocok. Ternyata Anda benar selama ini. Saya minta maaf karena butuh banyak waktu bagi saya untuk mendapatkannya.
ThunderGr

1

Solusi bekerja untuk bekerja dengan membuat acara alih-alih perubahan

Bahkan untuk menyalin, memotong, menempel, bergerak.

class Program
{        

        static void Main(string[] args)
        {
            string SourceFolderPath = "D:\\SourcePath";
            string DestinationFolderPath = "D:\\DestinationPath";
            FileSystemWatcher FileSystemWatcher = new FileSystemWatcher();
            FileSystemWatcher.Path = SourceFolderPath;
            FileSystemWatcher.IncludeSubdirectories = false;
            FileSystemWatcher.NotifyFilter = NotifyFilters.FileName;   // ON FILE NAME FILTER       
            FileSystemWatcher.Filter = "*.txt";         
             FileSystemWatcher.Created +=FileSystemWatcher_Created; // TRIGGERED ONLY FOR FILE GOT CREATED  BY COPY, CUT PASTE, MOVE  
            FileSystemWatcher.EnableRaisingEvents = true;

            Console.Read();
        }     

        static void FileSystemWatcher_Created(object sender, FileSystemEventArgs e)
        {           
                string SourceFolderPath = "D:\\SourcePath";
                string DestinationFolderPath = "D:\\DestinationPath";

                try
                {
                    // DO SOMETING LIKE MOVE, COPY, ETC
                    File.Copy(e.FullPath, DestinationFolderPath + @"\" + e.Name);
                }
                catch
                {
                }          
        }
}

Solusi untuk pengamat file ini saat acara perubahan atribut file menggunakan penyimpanan statis

class Program
{
    static string IsSameFile = string.Empty;  // USE STATIC FOR TRACKING

    static void Main(string[] args)
    {
         string SourceFolderPath = "D:\\SourcePath";
        string DestinationFolderPath = "D:\\DestinationPath";
        FileSystemWatcher FileSystemWatcher = new FileSystemWatcher();
        FileSystemWatcher.Path = SourceFolderPath;
        FileSystemWatcher.IncludeSubdirectories = false;
        FileSystemWatcher.NotifyFilter = NotifyFilters.LastWrite;          
        FileSystemWatcher.Filter = "*.txt";         
        FileSystemWatcher.Changed += FileSystemWatcher_Changed;
        FileSystemWatcher.EnableRaisingEvents = true;

        Console.Read();
    }     

    static void FileSystemWatcher_Changed(object sender, FileSystemEventArgs e)
    {
        if (e.Name == IsSameFile)  //SKIPS ON MULTIPLE TRIGGERS
        {
            return;
        }
        else
        {
            string SourceFolderPath = "D:\\SourcePath";
            string DestinationFolderPath = "D:\\DestinationPath";

            try
            {
                // DO SOMETING LIKE MOVE, COPY, ETC
                File.Copy(e.FullPath, DestinationFolderPath + @"\" + e.Name);
            }
            catch
            {
            }
        }
        IsSameFile = e.Name;
    }
}

Ini adalah solusi untuk masalah ini dari berbagai peristiwa pemicu.


0

Saya akan mengatakan menggunakan polling, terutama dalam skenario TDD, karena jauh lebih mudah untuk mengejek / mematikan keberadaan file atau sebaliknya ketika acara polling dipicu daripada bergantung pada acara fsw yang lebih "tidak terkontrol". + untuk yang telah bekerja pada sejumlah aplikasi yang diganggu oleh kesalahan fsw.

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.