FileSystemWatcher vs polling để xem thay đổi tập tin


152

Tôi cần thiết lập một ứng dụng theo dõi các tệp được tạo trong một thư mục, cả cục bộ hoặc trên ổ đĩa mạng.

Liệu FileSystemWatcherhoặc bỏ phiếu trên một bộ đếm thời gian sẽ là lựa chọn tốt nhất. Tôi đã sử dụng cả hai phương pháp trong quá khứ, nhưng không rộng rãi.

Có vấn đề gì (hiệu suất, độ tin cậy, v.v.) với một trong hai phương pháp?


3
FileSystemWatcher là một bản tóm tắt bị rò rỉ và không thể dựa vào bất cứ điều gì ngoại trừ những trường hợp cơ bản nhất. Xem tại đây: stackoverflow.com/a/22768610/129130
Stein smul

1
Muốn thêm một liên kết để tham khảo câu trả lời này của Raymond Chen (chuyên gia của Microsoft) về chủ đề độ tin cậy của FileSystemWatcher . Và blog của anh ấy: The Old New Thing (tìm kiếm FileSystemWatcher chẳng hạn).
Stein Åsmul

Câu trả lời:


105

Tôi đã thấy trình theo dõi hệ thống tập tin thất bại trong môi trường sản xuất và thử nghiệm. Bây giờ tôi coi đó là một sự tiện lợi, nhưng tôi không cho rằng nó đáng tin cậy. Mẫu của tôi đã theo dõi các thay đổi với trình theo dõi hệ thống tệp, nhưng thỉnh thoảng thăm dò để bắt các thay đổi tệp bị thiếu.

Chỉnh sửa: Nếu bạn có UI, bạn cũng có thể cung cấp cho người dùng khả năng "làm mới" để thay đổi thay vì bỏ phiếu. Tôi sẽ kết hợp điều này với một người theo dõi hệ thống tập tin.


11
Tôi cũng đã thấy nếu ngã xuống. Giải pháp chúng tôi đã sử dụng là bọc lớp riêng của chúng tôi, trong đó lớp bao bọc ALSO sử dụng bộ đếm thời gian để kiểm tra trong trường hợp người theo dõi vẫn đang đi.
Joel Coehoorn

Chúng tôi làm một cái gì đó tương tự - một khi chúng tôi đã xử lý tệp được chuyển vào sự kiện FileCreated, chúng tôi sẽ kiểm tra thủ công cho bất kỳ tệp mới nào khác trước khi quay lại. Điều này dường như để giảm thiểu bất kỳ vấn đề xảy ra với nhiều tệp đến cùng một lúc.
John Sizable

4
Tôi tin rằng chúng tôi đã thử nghiệm nó trong XP và Server 2003 trên một thư mục cục bộ và chia sẻ tệp và có các máy XP trong trường. Chúng tôi đã có vấn đề với cả thư mục và chia sẻ tệp cục bộ. Một trong những nguyên nhân có thể xảy ra mà chúng tôi đã đưa ra là việc sao chép / tạo rất nhiều tệp trong một khoảng thời gian ngắn trong thư mục.
Jason Jackson

5
Nó không mang tính xây dựng cũng không chuyên nghiệp khi chỉ nói rằng "tôi đã nhìn thấy một con ma một ngày". Dường như mọi người xuống luồng, đề cập đến tài liệu msDN về lỗi tràn bộ đệm không thể thoát trang có thể giải thích vấn đề của bạn. Bạn đã thử sử dụng phương pháp của Brent chưa?
v.oddou

4
Tôi mới mua một cảm biến khí trên Amazon và điều đó làm tôi ngạc nhiên khi nhiều người nói rằng nó không hoạt động, khi họ rõ ràng không hiệu chỉnh chính xác hoặc thậm chí không biết về hiệu chuẩn ... FileSystemWatcher đã biết những hạn chế với lưu lượng truy cập cao từ kích thước bộ đệm của nó. Hầu như đảm bảo rằng đó là lý do cho nó "thất bại". Điều này dễ dàng được giải thích trong tài liệu và có những công việc xung quanh cung cấp hoạt động rất đáng tin cậy (như được đăng dưới đây). Đây không phải là một câu trả lời tốt khi chỉ nói "errr, một cái gì đó đã không hoạt động một lần, không chắc tại sao ... không ai nên dựa vào nó".
u8it

60

Vấn đề lớn nhất tôi gặp phải là thiếu các tệp khi bộ đệm đầy. Dễ dàng như chiếc bánh để sửa chữa - chỉ cần tăng bộ đệm. Hãy nhớ rằng nó chứa tên tệp và sự kiện, vì vậy hãy tăng nó lên số lượng tệp dự kiến ​​(dùng thử và lỗi). Nó không sử dụng bộ nhớ không thể phân trang, vì vậy nó có thể buộc các quá trình khác chuyển sang trang nếu bộ nhớ thấp.

Đây là bài viết MSDN về bộ đệm: FileSystemWatcher .. ::. InternalBufferSize Thuộc tính

Mỗi MSDN:

Tăng kích thước bộ đệm là tốn kém, vì nó xuất phát từ bộ nhớ không phân trang không thể hoán đổi ra đĩa, vì vậy hãy giữ bộ đệm càng nhỏ càng tốt. Để tránh tràn bộ đệm, hãy sử dụng các thuộc tính NotifyFilter và gộpSubdirectories để lọc các thông báo thay đổi không mong muốn.

Chúng tôi sử dụng 16MB do một lô lớn dự kiến ​​cùng một lúc. Hoạt động tốt và không bao giờ bỏ lỡ một tập tin.

Chúng tôi cũng đọc tất cả các tệp trước khi bắt đầu xử lý ngay cả một ... lấy tên tệp được lưu trữ an toàn (trong trường hợp của chúng tôi, vào bảng cơ sở dữ liệu) sau đó xử lý chúng.

Đối với các sự cố khóa tệp, tôi tạo ra một quá trình chờ đợi để mở khóa tệp trong một giây, sau đó hai, rồi bốn, et cetera. Chúng tôi không bao giờ thăm dò ý kiến. Điều này đã được sản xuất mà không có lỗi trong khoảng hai năm.


12
Tràn bộ nhớ? Oh, bạn có nghĩa là chồng tràn.
TheFlash

1
Kể từ .NET 3.5: "Bạn có thể đặt bộ đệm thành 4 KB hoặc lớn hơn, nhưng không được vượt quá 64 KB"
brad

9
Bạn đang sử dụng 16MB như thế nào nếu bộ đệm trong tối đa cho FileSystemWatcher là 64KB?
BK

1
@ Jarvis, bộ đệm là một vị trí lưu trữ ôn hòa được cấu hình để lưu giữ thông tin khi nó được truyền cho đến khi nó có thể được xử lý, điều này thường có nghĩa là một FIFO hoặc Queue khi bạn muốn giải quyết các yêu cầu theo thứ tự chúng đến trong một số quy trình như đệ quy trong các chương trình cấu trúc FILO hoặc Stack là những gì được sử dụng, trong trường hợp này, chúng tôi chắc chắn đề cập đến bộ đệm hàng đợi sự kiện chứ không phải bộ đệm ngăn xếp cuộc gọi chương trình
MikeT

1
petermeinl.wordpress.com/2015/05/18/tamed-filesystemwatcher Bài đăng này chia sẻ các trình bao bọc mạnh mẽ xung quanh tiêu chuẩn sửa lỗi FileSystemWatcher (FSW) thường gặp khi sử dụng nó để giám sát hệ thống tệp trong các ứng dụng trong thế giới thực.
Kiquenet

35

Cũng FileSystemWatchercó thể bỏ lỡ các thay đổi trong thời gian bận rộn, nếu số lượng thay đổi được xếp hàng vượt quá bộ đệm được cung cấp. Đây không phải là giới hạn của lớp .NET mỗi lần, mà là cơ sở hạ tầng Win32 bên dưới. Theo kinh nghiệm của chúng tôi, cách tốt nhất để giảm thiểu vấn đề này là loại bỏ các thông báo càng nhanh càng tốt và xử lý chúng trên một chủ đề khác.

Như được đề cập bởi @ChillTemp ở trên, trình theo dõi có thể không hoạt động trên các cổ phiếu không phải của Windows. Ví dụ, nó hoàn toàn không hoạt động trên các ổ Novell được gắn.

Tôi đồng ý rằng một thỏa hiệp tốt là thực hiện một cuộc thăm dò không thường xuyên để nhận bất kỳ thay đổi bị bỏ lỡ.


4
Trình theo dõi hệ thống tập tin có thể bắt đầu đưa ra rất nhiều sự kiện liên tiếp. Nếu bạn không thể thực thi trình xử lý sự kiện của mình ít nhất là nhanh chóng khi chúng bị bắn, cuối cùng trình xử lý sẽ bắt đầu thả các sự kiện trên sàn và bạn sẽ bỏ lỡ mọi thứ.
Brent Rockwood

17

Cũng lưu ý rằng trình theo dõi hệ thống tệp không đáng tin cậy về chia sẻ tệp. Đặc biệt nếu chia sẻ tệp được lưu trữ trên một máy chủ không có cửa sổ. FSW không nên được sử dụng cho bất cứ điều gì quan trọng. Hoặc nên được sử dụng với một cuộc thăm dò không thường xuyên để xác minh rằng nó đã không bỏ sót điều gì.


3
Microsoft đã thừa nhận rằng nó không đáng tin cậy trên các chia sẻ tệp không phải windows? Chúng tôi chắc chắn đang trải nghiệm điều này đầu tiên kể từ khi chuyển từ chia sẻ Windows sang chia sẻ SMB dựa trên Linux.
Sean

1
Không phải là tôi biết. Và tôi chắc chắn rằng nó chỉ đơn giản là một trò chơi đổ lỗi giữa các nhà cung cấp khác nhau.
chilltemp

1
Chúng tôi đã gặp sự cố với trình theo dõi hệ thống tệp trên các ổ đĩa được ánh xạ. Nếu bản đồ ngắt kết nối và sau đó kết nối lại, trình xem tập tin không còn làm thay đổi. Dễ dàng giải quyết nhưng vẫn là một cuộc đình công chống lại người xem hệ thống tập tin IMHO.
Richard Dorman

11

Cá nhân tôi đã sử dụng FileSystemWatcherhệ thống sản xuất và nó hoạt động tốt. Trong 6 tháng qua, nó không có một trục trặc nào chạy 24x7. Nó đang theo dõi một thư mục cục bộ duy nhất (được chia sẻ). Chúng tôi có một số lượng hoạt động tệp tương đối nhỏ mà nó phải xử lý (10 sự kiện được thực hiện mỗi ngày). Đó không phải là điều tôi từng phải lo lắng. Tôi sẽ sử dụng nó một lần nữa nếu tôi phải làm lại quyết định.


7

Tôi hiện đang sử dụng FileSystemWatcher tệp XML được cập nhật trung bình cứ sau 100 mili giây.

Tôi đã thấy rằng miễn FileSystemWatcherlà cấu hình đúng, bạn sẽ không bao giờ gặp vấn đề với cục bộ tệp .

Tôi không có kinh nghiệm về xem tập tin từ xa và chia sẻ không phải Windows.

Tôi sẽ coi việc bỏ phiếu là không cần thiết và không đáng để chi trả trừ khi bạn không tin tưởng FileSystemWatcherhoặc đã trực tiếp gặp phải những hạn chế mà mọi người khác ở đây đã liệt kê (chia sẻ không phải Windows và xem tệp từ xa).


5

Tôi sẽ đi bỏ phiếu.

Sự cố mạng khiến FileSystemWatcherkhông đáng tin cậy (ngay cả khi quá tải sự kiện lỗi).


5

Tôi đã gặp rắc rối khi sử dụng FileSystemWatchertrên các chia sẻ mạng. Nếu bạn đang ở trong một môi trường Windows thuần túy, đó có thể không phải là vấn đề, nhưng tôi đã xem một chia sẻ NFS và vì NFS không trạng thái, nên không bao giờ có thông báo khi tệp tôi đang xem thay đổi.


Tôi đã gặp vấn đề tương tự, nhưng thật bất ngờ với tôi vì FileSystemWatcher nằm trên cùng một máy chủ windows chia sẻ thư mục bằng NFS. thực tế chia sẻ một thư mục với NFS làm cho trình xem hệ thống tập tin không thấy các tệp được tạo bằng chia sẻ từ xa (tức là từ Linux có ánh xạ chia sẻ) trong khi nếu tôi viết một tệp trên cùng một thư mục được theo dõi, thì trình theo dõi hệ thống tập tin được kích hoạt. Dường như máy chủ NFS ghi các tệp bằng cách sử dụng lớp thấp hơn và lớp api kích hoạt fthe filesystemwatcher không được tham gia, có ai có thêm thông tin không?
Mosè Bottacini

3

Tôi gặp một số vấn đề lớn với FSW trên các ổ đĩa mạng: Xóa một tệp luôn gây ra sự kiện lỗi, không bao giờ là sự kiện bị xóa. Tôi không tìm thấy giải pháp, vì vậy bây giờ tôi tránh FSW và sử dụng bỏ phiếu.

Mặt khác, các sự kiện tạo hoạt động tốt, vì vậy nếu bạn chỉ cần xem để tạo tệp, bạn có thể đi đến FSW.

Ngoài ra, tôi không có vấn đề gì với các thư mục cục bộ, bất kể có chia sẻ hay không.


3

Trở về từ phương thức sự kiện càng nhanh càng tốt, sử dụng một luồng khác, đã giải quyết vấn đề cho tôi:

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

2

Sử dụng cả FSW bỏ phiếu là một sự lãng phí thời gian và tài nguyên, theo tôi, và tôi ngạc nhiên khi các nhà phát triển có kinh nghiệm đề xuất nó. Nếu bạn cần sử dụng bỏ phiếu để kiểm tra bất kỳ "lỗi FSW" nào, thì bạn có thể loại bỏ hoàn toàn FSW và chỉ sử dụng bỏ phiếu.

Tôi hiện đang cố gắng quyết định xem tôi sẽ sử dụng FSW hay bỏ phiếu cho dự án mà tôi phát triển. Đọc câu trả lời, rõ ràng có những trường hợp mà FSW đáp ứng nhu cầu một cách hoàn hảo, trong khi những lần khác, bạn cần bỏ phiếu. Thật không may, không có câu trả lời nào thực sự xử lý sự khác biệt về hiệu suất (nếu có), chỉ với các vấn đề "độ tin cậy". Có ai có thể trả lời một phần của câu hỏi không?

EDIT: quan điểm của nmclean về tính hợp lệ của việc sử dụng cả FSW và bỏ phiếu (bạn có thể đọc thảo luận trong các bình luận, nếu bạn quan tâm) dường như là một lời giải thích rất hợp lý tại sao có thể có tình huống sử dụng cả FSW và bỏ phiếu Có hiệu quả. Cảm ơn bạn đã làm sáng tỏ điều đó cho tôi (và bất cứ ai khác có cùng quan điểm), nmclean .


1
Điều gì nếu bạn muốn phản hồi thay đổi tập tin càng nhanh càng tốt? Ví dụ, nếu bạn thăm dò ý kiến ​​một lần mỗi phút, bạn có thể có độ trễ tối đa 1 phút giữa một lần thay đổi tệp và ứng dụng của bạn chọn thay đổi. Sự kiện FSW có lẽ sẽ được kích hoạt nhiều trước đó. Vì vậy, bằng cách sử dụng cả hai bạn đang xử lý các sự kiện với độ trễ ít nhất có thể, nhưng cũng chọn các sự kiện bị bỏ lỡ nếu có.
rom99

@ rom99 Chính xác là quan điểm của tôi. Nếu FSW không đáng tin cậy trong trường hợp bạn cần phản hồi nhanh, thì không có lý do gì để sử dụng nó, vì bạn sẽ có trường hợp sẽ không có phản hồi nhanh, do đó, ứng dụng của bạn sẽ không đáng tin cậy. Bỏ phiếu trong khoảng thời gian ngắn hơn, trong một chủ đề, sẽ là những gì bạn cần làm. Bằng cách thực hiện cả hai , có nghĩa là bạn có một dung sai trong thời gian phản hồi mà bỏ phiếu, vì vậy, tại sao không sử dụng chỉ bỏ phiếu?
ThunderGr

5
@ThunderGr "do đó, ứng dụng của bạn sẽ không đáng tin cậy." - Trong nhiều trường hợp, tốc độ không phải là điều kiện tiên quyết cho độ tin cậy. Công việc phải được thực hiện, nhưng nó có thể chờ một lúc. Nếu chúng ta kết hợp bỏ phiếu chậm, đáng tin cậy với FSW nhanh, không đáng tin cậy , chúng ta sẽ nhận được một ứng dụng luôn đáng tin cậy đôi khi nhanh, tốt hơn đáng tin cậy và không bao giờ nhanh. Chúng tôi có thể loại bỏ FSW và đạt được thời gian phản hồi tối đa tương tự bằng cách thực hiện bỏ phiếu liên tục, nhưng điều này phải trả giá bằng khả năng đáp ứng của phần còn lại của ứng dụng, do đó chỉ nên được thực hiện nếu cần phải có phản hồi ngay lập tức.
nmclean

2
Bây giờ tại sao ở trên là một lập luận nghèo? Bởi vì, mặc dù chúng tôi vẫn cần truy cập đĩa, chúng tôi cần ít hơn . Tương tự, bạn có thể thăm dò ý kiến ​​ít hơn. Chỉ vì chúng tôi vẫn kiểm tra tất cả các tệp không có nghĩa là khối lượng công việc là như nhau. Câu nói của bạn, "bỏ phiếu có tốn kém về thời gian CPU với FSW hay không," là sai . Bằng cách giảm tải mối quan tâm "tức thời" cho FSW, chúng tôi có thể thay đổi việc bỏ phiếu thành một nhiệm vụ nhàn rỗi, mức độ ưu tiên thấp, để sự bận rộn của ứng dụng tại bất kỳ thời điểm nào được giảm đáng kể trong khi vẫn cung cấp "điều trị" cho tính trực tiếp. Bạn chỉ đơn giản là không thể đạt được sự cân bằng tương tự với bỏ phiếu một mình.
nmclean

9
@nmclean Cảm ơn bạn đã dành thời gian và năng lượng để làm rõ điều này theo cách bạn đã làm. Khi bạn đặt nó theo cách đó, nó chắc chắn có ý nghĩa hơn nhiều. Cũng giống như có những lúc bộ đệm không phù hợp với vấn đề cụ thể của bạn, do đó, FSW (khi nó chứng minh không đáng tin cậy) có thể không phù hợp. Nó chỉ ra rằng bạn đã đúng tất cả cùng. Tôi xin lỗi phải mất rất nhiều thời gian để tôi có được nó.
ThunderGr

1

Giải pháp làm việc để làm việc với tạo sự kiện thay vì thay đổi

Ngay cả để sao chép, cắt, dán, di chuyển.

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

Giải pháp cho trình xem tệp này trong khi sự kiện thay đổi thuộc tính tệp bằng cách sử dụng bộ nhớ tĩnh

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

Đây là một giải pháp khắc phục cho vấn đề nhiều sự kiện kích hoạt này.


0

Tôi sẽ nói rằng sử dụng bỏ phiếu, đặc biệt là trong kịch bản TDD, vì việc giả lập / loại bỏ sự hiện diện của các tệp dễ dàng hơn nhiều hoặc khi sự kiện bỏ phiếu được kích hoạt hơn là dựa vào sự kiện fsw "không kiểm soát" hơn. + đã làm việc trên một số ứng dụng bị lỗi bởi các lỗi fsw.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.