FileSystemWatcher बदल घटना दो बार उठाया जाता है


335

मेरे पास एक एप्लिकेशन है जहां मैं एक टेक्स्ट फ़ाइल की तलाश कर रहा हूं और यदि फ़ाइल में किए गए कोई भी परिवर्तन हैं तो मैं OnChangedईवेंट हैंडल करने के लिए ईवेंटहैंडलर का उपयोग कर रहा हूं । मैं उपयोग कर रहा हूं, NotifyFilters.LastWriteTimeलेकिन फिर भी घटना दो बार हो रही है। यहाँ कोड है।

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

मेरे मामले में OnChangedदो बार कॉल किया जाता है, जब मैं टेक्स्ट फ़ाइल को बदल देता हूं version.txtऔर इसे सहेजता हूं ।


2
@BrettRigby: कोई आश्चर्य नहीं। इन संभावित उत्तरों में से कोई भी समस्या का समाधान प्रदान नहीं करता है। वे सभी विशिष्ट मुद्दों के लिए वर्कअराउंड हैं। वास्तव में, उनमें से किसी ने मेरी विशिष्ट समस्या को हल नहीं किया (मुझे मानना ​​चाहिए, मैंने उन सभी का परीक्षण नहीं किया है)।

यह एक वर्कअराउंड है, लेकिन इसे वर्कअराउंड की गुणवत्ता से आंका जाना चाहिए। परिवर्तनों पर नज़र रखना पूरी तरह से काम करता है, और यह सरल है। ओपी डुप्लिकेट घटनाओं को दबाने का एक तरीका पूछ रहा है, और यही नीचे दी गई प्रतिक्रियाएं हैं। msdn.microsoft.com/en-us/library/… बताते हैं कि एंटी-वायरस, या अन्य "जटिल फ़ाइल सिस्टम सामान" (जो सिर्फ एक बहाना लगता है) के कारण कई घटनाएं हो सकती हैं।
टायलर मोंटेनी

2
मैंने हाल ही में इस मुद्दे का विरोध किया github.com/Microsoft/dotnet/issues/347
विरोध किया Stephan Ahlf

2
मैंने एक वर्ग बनाया है जो आपको केवल एक घटना प्राप्त करने में मदद करता है। आप github.com/melenaos/FileSystemSafeWatcher
Menelaos Vergis

जवाबों:


276

मुझे डर है कि यह FileSystemWatcherवर्ग का एक प्रसिद्ध बग / विशेषता है । यह वर्ग के प्रलेखन से है:

आप कुछ स्थितियों में नोटिस कर सकते हैं कि एक एकल निर्माण घटना आपके घटक द्वारा नियंत्रित कई सृजित घटनाओं को उत्पन्न करती है। उदाहरण के लिए, यदि आप किसी निर्देशिका में नई फ़ाइलों के निर्माण की निगरानी के लिए एक FileSystemWatcher घटक का उपयोग करते हैं, और फिर एक फ़ाइल बनाने के लिए नोटपैड का उपयोग करके इसका परीक्षण करते हैं, तो आप केवल एक ही फ़ाइल बनाई गई दो सृजित घटनाओं को देख सकते हैं। ऐसा इसलिए है क्योंकि नोटपैड लेखन प्रक्रिया के दौरान कई फाइल सिस्टम एक्शन करता है। नोटपैड उन बैचों में डिस्क को लिखता है जो फ़ाइल की सामग्री बनाते हैं और फिर फ़ाइल विशेषताएँ। अन्य अनुप्रयोग उसी तरीके से प्रदर्शन कर सकते हैं। क्योंकि FileSystemWatcher ऑपरेटिंग सिस्टम की गतिविधियों पर नज़र रखता है, इन अनुप्रयोगों में आग लगने वाली सभी घटनाओं को उठाया जाएगा।

अब यह थोड़ा सा पाठ Createdघटना के बारे में है , लेकिन यही बात अन्य फ़ाइल घटनाओं पर भी लागू होती है। कुछ अनुप्रयोगों में आप इसका उपयोग करके इसे प्राप्त करने में सक्षम हो सकते हैंNotifyFilter संपत्ति हैं, लेकिन मेरा अनुभव यह कहता है कि कभी-कभी आपको कुछ मैनुअल डुप्लिकेट फ़िल्टरिंग (हैक्स) भी करना पड़ता है।

कुछ समय पहले मैंने कुछ FileSystemWatcher युक्तियों वाले एक पृष्ठ को बुकमार्क किया था । शायद आप इस पर एक नजर डालना चाहें।



151

मैंने अपने प्रतिनिधि में निम्नलिखित रणनीति का उपयोग करके "समस्या" तय की है:

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

14
मैंने कोशिश की कि यह काम करे और अगर मैंने एक बार में एक फ़ाइल को संशोधित किया है, लेकिन अगर मैंने एक बार में दो फ़ाइलों को संशोधित किया है (जैसे प्रतिलिपि 1.txt और 2.txt की प्रतिलिपि 1.txt और 2.txt की प्रतिलिपि) एक घटना उम्मीद के मुताबिक दो नहीं।
क्रिस्टोफर पेंटर

2
एक दो महीने हो गए हैं, लेकिन मुझे लगता है कि मैंने जो किया, वह इस घटना को एक ऐसा तरीका बता रहा है, जो लॉजिक स्टेटमेंट के अंदर व्यावसायिक तर्क देता है। इस तरह अगर मुझे अतिरिक्त कार्यक्रम मिलते हैं तो वे तब तक कतार में लगते हैं जब तक कि उनकी बारी न हो और उनके लिए कुछ भी नहीं है क्योंकि पिछले पुनरावृत्ति ने सब कुछ संभाल लिया था।
क्रिस्टोफर पेंटर

15
यह समस्या को हल करने के लिए प्रकट होता है, लेकिन ऐसा नहीं है। यदि कोई अन्य प्रक्रिया परिवर्तन कर रही है, तो आप उन्हें खो सकते हैं, इसका कारण यह प्रतीत होता है कि काम करना है क्योंकि अन्य प्रक्रिया का IO async है, और जब तक आप अपनी प्रक्रिया पूरी नहीं कर लेते, तब तक आप निगरानी अक्षम कर देते हैं, इस प्रकार अन्य घटनाओं के साथ दौड़ की स्थिति बन सकती है। ब्याज की। इसीलिए @ChristopherPainter ने उनके मुद्दे को देखा।
जेफ ब्यूलैक

14
-1: क्या होगा यदि एक और परिवर्तन जो आप अक्षम होते समय करना चाहते हैं?
जी। स्टोयनेव

2
@cYounes: जब तक आप अपना सामान एसिंक्रोनस रूप से नहीं करते।
डेविड ब्रेबंट

107

प्रश्न में फ़ाइल पर टाइमस्टैम्प की जांच करके किसी भी डुप्लिकेट किए गए OnChangedईवेंट का FileSystemWatcherपता लगाया और खारिज किया जा सकता है File.GetLastWriteTime। इस तरह:

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
}

13
मुझे वह समाधान पसंद है, लेकिन मैंने "सही" चीज़ करने के लिए Rx का उपयोग किया है (आप जिस चीज़ "Rename"में रुचि रखते हैं, उसके नाम में बदलाव करें):Observable.FromEventPattern<FileSystemEventArgs>(fileSystemWatcher, "Renamed") .Select(e => e.EventArgs) .Distinct(e => e.FullPath) .Subscribe(onNext);
Kjellski

4
क्या मैं कुछ भूल रहा हूँ? मुझे समझ नहीं आता कि यह कैसे काम करेगा। Ive ने घटनाओं को एक साथ आग में देखा था, इसलिए यदि वे दोनों एक ही समय में उपरोक्त घटना में प्रवेश करते हैं, तो वे दोनों अंतिम दौड़ से पहले दौड़ना शुरू कर देंगे।
पीटर जैम्सनसन

के रूप में DateTimeकेवल मिलीसेकंड संकल्प है, इस पद्धति भले ही आप की जगह काम करता है File.GetLastWriteTimeके साथ DateTime.Now। अपनी स्थिति के आधार पर, आप a.FullNameडुप्लिकेट घटनाओं का पता लगाने के लिए एक वैश्विक चर में उपयोग कर सकते हैं ।
रोलैंड

@PeterJamsmenson घटनाएं एक साथ आग नहीं लगाती हैं। उदाहरण के लिए, नोटपैड डिस्क में संशोधनों को सहेजते समय कई घटनाओं को उत्पन्न कर सकता है, लेकिन इन घटनाओं को क्रमिक रूप से निकाल दिया जाता है, एक के बाद एक, कई चरणों के दौरान जिसे नोटपैड को बचाने के लिए प्रदर्शन करने की आवश्यकता होती है। बाबू का तरीका बढ़िया काम करता है।
रोलैंड

10
के रूप में काम नहीं किया घटनाओं के रूप में निकाल दिया जाता है अलग हैं: अंतिम समय लिखें: 636076274162565607 अंतिम समय लिखें: 636076274162655722
Asheh

23

यहाँ मेरा समाधान है जिसने मुझे दो बार उठाए जा रहे आयोजन को रोकने में मदद की:

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

यहां मैंने NotifyFilterकेवल फ़ाइल नाम और आकार के साथ संपत्ति निर्धारित की है ।
watcherFileSystemWatcher की मेरी वस्तु है। आशा है कि यह मदद करेगा।


9
इसके अलावा, नोटपैड में, मैंने चार वर्णों के साथ एक फ़ाइल बनाई: इसमें abcd। मैंने तब नोटपैड का एक नया उदाहरण खोला और उसी चार वर्णों में प्रवेश किया। मैंने फाइल चुनी | इस तरह सेव करें और उसी फाइल को चुने। फ़ाइल समान है और आकार और फ़ाइल नाम नहीं बदलता है, क्योंकि फ़ाइल में एक ही चार अक्षर हैं, इसलिए यह आग नहीं करता है।
रिहायस

30
यह संभव है कि एक वास्तविक परिवर्तन किया जा सकता है जो फ़ाइल के आकार में परिवर्तन नहीं करता है, इसलिए यह तकनीक उस स्थिति में विफल हो जाएगी।
ली ग्रिसॉम

3
मुझे लगता है कि यह एक काफी सामान्य मामला है जहां आप जानते हैं कि कोई भी सार्थक परिवर्तन फ़ाइल आकार को संशोधित करेगा (उदाहरण के लिए, मेरा मामला लॉग फ़ाइल में संलग्न था)। जबकि जो कोई भी इस समाधान का उपयोग करता है, उस धारणा के बारे में (और दस्तावेज़) से अवगत होना चाहिए, यह वही था जो मुझे चाहिए था।
ग्रैंडऑपनर

1
@GrandOpener: यह हमेशा सच नहीं होता है। मेरे मामले में मैं उन फाइलों को देख रहा हूँ जहाँ इसकी सामग्री में केवल एक वर्ण होता है जो कि 0 या 1. है

8

मेरा परिदृश्य यह है कि मेरे पास लिनक्स सर्वर के साथ एक आभासी मशीन है। मैं विंडोज होस्ट पर फाइलें विकसित कर रहा हूं। जब मैं होस्ट पर एक फ़ोल्डर में कुछ बदलता हूं तो मैं चाहता हूं कि सभी परिवर्तन अपलोड हो जाएं, वर्चुअल सर्वर पर Ftp के माध्यम से सिंक किया जाए। जब मैं फ़ाइल में लिखता हूं, तो मैं डुप्लिकेट परिवर्तन की घटना को समाप्त कर देता हूं (जो फ़ाइल को फ़ोल्डर में बदल देता है और साथ ही संशोधित किया जाता है):

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

मुख्य रूप से मैं फ़ाइल लिखने की समय जानकारी संग्रहीत करने के लिए एक हैशटेबल बनाता हूं। फिर अगर हैशटेबल में फ़ाइलपथ है जिसे संशोधित किया गया है और यह समय का मूल्य है जो वर्तमान में अधिसूचित फ़ाइल के परिवर्तन के समान है, तो मुझे पता है कि यह घटना का डुप्लिकेट है और इसे अनदेखा करें।


मुझे लगता है कि आप समय-समय पर हैशटेबल को खाली करते हैं।
थंडरग्रो

यह दूसरे के लिए सटीक होगा, लेकिन यदि दो परिवर्तनों के बीच की अवधि एक दूसरे को पारित करने के लिए काफी लंबी है तो यह विफल हो जाएगा। इसके अलावा यदि आप अधिक सटीकता चाहते हैं तो आप उपयोग कर सकते हैं ToString("o")लेकिन अधिक विफलताओं के लिए तैयार रहें।
प्रागमेटेक

5
तार की तुलना न करें, DateTime.Equals ()
फिलिप Kamikaze

नहीं, नहीं। वे बराबर नहीं हैं। मेरे वर्तमान प्रोजेक्ट के मामले में, वे एक मिलीसेकंड से अलग हैं। मैं (newtime-oldtime) .TotalMilliseconds का उपयोग करता हूं <(मनमाने ढंग से दहलीज, आमतौर पर 5ms)।
फ्लायन 1179 15

8

इस कोड के साथ प्रयास करें:

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

1
यह सबसे अच्छा समाधान है, टाइमर के बजाय सेमाफोर का उपयोग करना।
हारून ब्लेंकुष

1
क्या अर्धवृत्त? मुझे यहाँ सिर्फ एक बूलियन चर दिखाई देता है। इसके अलावा, मुख्य मुद्दा हल नहीं है: FileSystemEventHandler अभी भी कई घटनाओं को निकाल रहा है। और इस कोड का क्या प्रभाव है? if (let==false) { ... } else { let = false; }? अविश्वसनीय यह कैसे बढ़ा, यह केवल StackOverflow बैज का मामला होना चाहिए।
s 14:unıɐ ɐ qɐp

8

यहाँ मेरा दृष्टिकोण है:

// Consider having a List<String> 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();
}

यह वह समाधान है जिसका उपयोग मैं इस मुद्दे को एक परियोजना पर हल करने के लिए करता हूं जहां मैं एक मेल में संलग्नक के रूप में फाइल भेज रहा था। यह एक छोटे से टाइमर अंतराल के साथ भी दो बार गोलीबारी की घटना से आसानी से बच जाएगा, लेकिन मेरे मामले में 1000 ठीक था क्योंकि मैं मेलबॉक्स को प्रति सेकंड 1 संदेश के साथ बाढ़ की तुलना में कुछ परिवर्तनों को याद करने के साथ खुश था। कम से कम यह ठीक काम करता है अगर ठीक उसी समय कई फाइलें बदल दी जाएं।

एक और उपाय जो मैंने सोचा है कि सूची को एक मैपिंग फ़ाइलों के साथ उनके संबंधित एमडी 5 में बदलना होगा, इसलिए आपको एक मनमाना अंतराल नहीं चुनना होगा क्योंकि आपको प्रविष्टि को हटाना नहीं होगा, लेकिन इसके मूल्य को अपडेट करना होगा, और यदि यह नहीं बदला है तो अपना सामान रद्द करें। इसका एक पहलू यह है कि फ़ाइलों की निगरानी की जाने वाली मेमोरी में डिक्शनरी बढ़ रही है और अधिक से अधिक मेमोरी खा रहे हैं, लेकिन मैंने कहीं पढ़ा है कि मॉनिटर की गई फ़ाइलों की मात्रा FSW के आंतरिक बफर पर निर्भर करती है, इसलिए शायद यह महत्वपूर्ण नहीं है। पता नहीं कैसे MD5 कंप्यूटिंग समय आपके कोड के प्रदर्शन को प्रभावित करेगा, सावधान = \


आपका समाधान मेरे लिए बहुत अच्छा काम करता है। केवल, आप _changedFiles सूची में फ़ाइल जोड़ना भूल गए। कोड का पहला भाग इस तरह दिखना चाहिए:lock (_changedFiles) { if (_changedFiles.Contains(e.FullPath)) { return; } _changedFiles.Add(e.FullPath); // add this! } // do your stuff
davidthegrey

मैंने 4 जवाब ऊपर दिए और एक को उखाड़ फेंका। आपका उत्तर पहले वाला वही कर रहा है जो उसे LAST घटना को अंजाम देना चाहिए न कि पहले वाले को। जैसा कि @ जर्न द्वारा समझाया गया है कि समस्या बैचों में लिखी गई है। अन्य समाधान मेरे काम नहीं आए।
कोडिंगयूरलाइफ

आपका समाधान धागा-सुरक्षित नहीं है। _changedFilesएक से अधिक थ्रेड से पहुँचा है। इसे ठीक करने का एक तरीका ConcurrentDictionaryइसके बजाय उपयोग करना है List। दूसरा तरीका संपत्ति के साथ-साथ संपत्ति Formको वर्तमान आवंटित Timer.SynchronizingObjectकरना FileSystemWatcher.SynchronizingObjectहै।
थियोडोर जूलियास

5

मैंने एक वर्ग के साथ Git रेपो बनाया है जो विस्तार करता है FileSystemWatcher केवल कॉपी होने पर घटनाओं को ट्रिगर करने के लिए होता है। यह सभी बदली हुई घटनाओं को अंतिम रूप देता है और इसे केवल तभी बढ़ाता है जब फ़ाइल पढ़ने के लिए उपलब्ध हो जाती है।

डाउनलोड FileSystemSafeWatcher और इसे अपनी परियोजना में जोड़ें।

फिर इसे एक सामान्य के रूप में उपयोग करें FileSystemWatcherऔर घटनाओं के ट्रिगर होने पर निगरानी करें।

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

जब कोई ईवेंट किसी निर्देशिका पर उठाया जाता है तो यह विफल प्रतीत होता है। मुझे फ़ाइल खोलने से पहले डायरेक्टरी चेक लपेटकर काम करने के लिए मिला
सैम

उदाहरण में टाइपो के बावजूद, यह मेरे लिए एक व्यवहार्य समाधान प्रतीत होता है। हालांकि, मेरे मामले में एक सेकंड के भीतर एक दर्जन अपडेट हो सकते हैं, इसलिए मुझे किसी भी बदलाव को याद नहीं करने के लिए _consolidationInterval को कम करना पड़ा। जबकि 10 एमएस ठीक प्रतीत होता है, अगर मैं _consolidationInterval को 50 एमएस में सेट करता हूं, तो मैं अभी भी लगभग 50% अपडेट को ढीला कर देता हूं। मुझे अभी भी कुछ परीक्षण चलाने हैं जो सबसे अच्छा फिट बैठता है।

_consolidationInterval मेरे लिए अच्छा काम करता है। मैं किसी को यह कांटा बनाना चाहता हूँ और इसे एक NuGet पैकेज बनाना चाहता हूँ।
zumalifeguard

1
धन्यवाद :) यह मेरी समस्या हल हो गई .. उम्मीद है कि बनाई गई और कॉपी की गई घटनाएं इस समस्या को अच्छी तरह से हल करने के लिए एक एकल द्रष्टा के साथ ठीक से काम करेंगी। stackoverflow.com/questions/55015132/…
टेक्नो

1
यह उत्कृष्ट है। मैंने इसे अपनी परियोजना में लागू किया है और इसे तोड़ने की कोशिश में मैंने जो भी प्रयास किया है, उसे हरा दिया है। धन्यवाद।
क्रिसथ

4

मुझे पता है कि यह एक पुराना मुद्दा है, लेकिन एक ही समस्या थी और उपरोक्त समाधान में से कोई भी वास्तव में उस समस्या के लिए चाल नहीं था जो मैं सामना कर रहा था। मैंने एक डिक्शनरी बनाई है जो लास्टवेरिटाइम के साथ फाइल का नाम मैप करती है। तो अगर फाइल डिक्शनरी में नहीं है, तो प्रक्रिया के साथ आगे बढ़ेंगे, यह देखने के लिए कि अन्य संशोधित समय कब था और यह डिक्शनरी चलाने के दौरान कोड से अलग है।

    Dictionary<string, DateTime> dateTimeDictionary = new Dictionary<string, DateTime>(); 

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

यह एक ठोस समाधान है, लेकिन इसके कोड की एक पंक्ति गायब है। में your code hereअनुभाग में, आप जोड़ सकते हैं या dateTimeDictionary अद्यतन करना चाहिए। dateTimeDictionary[e.FullPath] = System.IO.File.GetLastWriteTime(e.FullPath);
डायमंडड्रेक

मेरे लिए काम नहीं किया। मेरे परिवर्तन हैंडलर को दो बार कहा जाता है और फ़ाइल में दूसरी बार एक अलग टाइमस्टैम्प है। हो सकता है क्योंकि यह एक बड़ी फ़ाइल है और पहली बार लेखन प्रगति पर था। मुझे लगता है कि नकल करने वाली घटनाओं को बेहतर बनाने के लिए मुझे एक टाइमर मिला।
माइकल

3

एक संभव 'हैक' उदाहरण के लिए प्रतिक्रियाशील एक्सटेंशन का उपयोग करके घटनाओं को कुचलना होगा:

var watcher = new FileSystemWatcher("./");

Observable.FromEventPattern<FileSystemEventArgs>(watcher, "Changed")
            .Throttle(new TimeSpan(500000))
            .Subscribe(HandleChangeEvent);

watcher.EnableRaisingEvents = true;

इस मामले में, मैं अपने सिस्टम पर 50ms के लिए थ्रॉटलिंग कर रहा हूं, जो पर्याप्त था, लेकिन उच्च मूल्य सुरक्षित होना चाहिए। (और जैसा मैंने कहा, यह अभी भी एक 'हैक' है)।


मैंने उपयोग किया है .Distinct(e => e.FullPath)जिससे निपटने के लिए मुझे अधिक सहज तरीका मिल गया है। और आपको वह व्यवहार वापस मिल गया है जो एपीआई से अपेक्षित होगा।
केजेल्स्की

3

मेरे पास यहां बहुत ही त्वरित और सरल वर्कअराउंड है, यह मेरे लिए काम करता है, और कोई बात नहीं घटना कभी-कभी एक या दो या अधिक बार ट्रिगर हो जाएगी, इसे देखें:

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

पहले तो मुझे लगा कि यह मेरे लिए काम करेगा, लेकिन ऐसा नहीं है। मेरे पास एक स्थिति है, जहां फ़ाइलों की सामग्री कभी-कभी केवल ओवरराइट की जाती है और दूसरी बार फ़ाइल को हटा दिया जाता है और पुनः बनाया जाता है। जब आपका समाधान फ़ाइल अधिलेखित होने की स्थिति में काम करने लगता है, तो फ़ाइल के पुनः बनाए जाने की स्थिति में यह हमेशा काम नहीं करता है। उत्तरार्द्ध मामले में कभी-कभी घटनाएं घट जाती हैं।

विभिन्न प्रकार की घटनाओं को सुलझाने और उनके साथ अलग से निपटने की कोशिश करें, मैं बस एक संभावित समाधान प्रदान करता हूं। सौभाग्य।
Xiaoyuvax

हालांकि इसका परीक्षण नहीं किया है, लेकिन मुझे यकीन नहीं है कि यह निर्माण और विलोपन के लिए काम नहीं करता है। यह सैद्धांतिक रूप से भी लागू होना चाहिए। फायरकाउंट ++ और अगर () स्टेटमेंट दोनों परमाणु हैं और प्रतीक्षा करने के लिए नहीं डाले जाएंगे। यहां तक ​​कि दो ट्रिगर की घटनाओं के साथ एक दूसरे के साथ प्रतिस्पर्धा। मुझे लगता है कि आपकी परेशानी का कारण कुछ और होना चाहिए। (खो से? आपका क्या मतलब है?)
Xiaoyuvax

3

यहां एक नया समाधान है जिसे आप आजमा सकते हैं। मेरे लिए अच्छा काम करता है। बदले हुए इवेंट के लिए हैंडलर में प्रोग्रामर डिजाइनर आउटपुट से एक संदेश को हटा दें यदि वांछित है तो प्रोग्रामेटिक रूप से हैंडलाइट वापस जोड़ें। उदाहरण:

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

1
आपको प्रतिनिधि प्रकार के निर्माता को आमंत्रित करने की आवश्यकता नहीं है। this.fileSystemWatcher1.Changed -= this.fileSystemWatcher1_Changed;सही काम करना चाहिए।
21

इसके लिए @bartonjs धन्यवाद। मुझे यकीन नहीं है कि मैंने पूरे निर्माता को क्यों बुलाया। ईमानदारी से इसकी सबसे अधिक संभावना एक नौसिखिया गलती है। भले ही ऐसा लगता है कि मेरे फिक्स के हैक ने काफी अच्छा काम किया है।
फैंसी_मथ

2

मुख्य कारण पहली घटना का अंतिम पहुंच समय वर्तमान समय था (फ़ाइल लिखना या परिवर्तित समय)। तब दूसरी घटना फ़ाइल का मूल अंतिम एक्सेस समय था। मैं कोड के तहत हल करता हूं।

        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;


2

मैंने FileSystemWatcher का उपयोग करते हुए कुछ महत्वपूर्ण समय बिताया, और यहां कुछ दृष्टिकोण काम नहीं करेंगे। मुझे वास्तव में अक्षम करने वाले ईवेंट दृष्टिकोण पसंद हैं, लेकिन दुर्भाग्य से, यह काम नहीं करता है अगर> 1 फ़ाइल को गिराया जा रहा है, तो दूसरी फ़ाइल सबसे अधिक बार याद की जाएगी यदि नहीं। इसलिए मैं निम्नलिखित दृष्टिकोण का उपयोग करता हूं:

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

2

इस कोड ने मेरे लिए काम किया।

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

2

ज्यादातर मुझे भविष्य के लिए :)

मैंने Rx का उपयोग करते हुए एक आवरण लिखा:

 public class WatcherWrapper : IDisposable
{
    private readonly FileSystemWatcher _fileWatcher;
    private readonly Subject<FileSystemEventArgs> _infoSubject;
    private Subject<FileSystemEventArgs> _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<FileSystemEventArgs>();
        _eventSubject = new Subject<FileSystemEventArgs>();

        Observable.FromEventPattern<FileSystemEventArgs>(_fileWatcher, "Changed").Select(e => e.EventArgs)
            .Subscribe(_infoSubject.OnNext);
        Observable.FromEventPattern<FileSystemEventArgs>(_fileWatcher, "Created").Select(e => e.EventArgs)
            .Subscribe(_infoSubject.OnNext);
        Observable.FromEventPattern<FileSystemEventArgs>(_fileWatcher, "Deleted").Select(e => e.EventArgs)
            .Subscribe(_infoSubject.OnNext);
        Observable.FromEventPattern<FileSystemEventArgs>(_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<FileSystemEventArgs> FileEvents => _eventSubject;


    public void Dispose()
    {
        _fileWatcher?.Dispose();
        _eventSubject.Dispose();
        _infoSubject.Dispose();
    }
}

उपयोग:

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)

1

मैंने निर्देशिकाओं में फ़ाइलों की निगरानी के तरीके को बदल दिया है। FileSystemWatcher का उपयोग करने के बजाय मैं एक और थ्रेड पर लोकेशन पोल करता हूं और फिर फाइल के लास्टवेरिटाइम को देखता हूं।

DateTime lastWriteTime = File.GetLastWriteTime(someFilePath);

इस जानकारी का उपयोग करना और फ़ाइल पथ का एक इंडेक्स रखना और यह नवीनतम लेखन समय है मैं उन फ़ाइलों को निर्धारित कर सकता हूं जो बदल गए हैं या जो किसी विशेष स्थान पर बनाई गई हैं। यह मुझे FileSystemWatcher की विषमताओं से दूर करता है। मुख्य नकारात्मक पक्ष यह है कि आपको LastWriteTime और फ़ाइल के संदर्भ को संग्रहीत करने के लिए एक डेटा संरचना की आवश्यकता है, लेकिन यह विश्वसनीय और लागू करना आसान है।


9
साथ ही साथ आपको सिस्टम ईवेंट द्वारा अधिसूचित होने के बजाय बैकग्राउंड साइकिल जलानी होगी।
मैथ्यू व्हिट

1

आप इसे लिखने के लिए खोलने का प्रयास कर सकते हैं, और यदि सफल है तो आप मान सकते हैं कि अन्य एप्लिकेशन फ़ाइल के साथ किया गया है।

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

सिर्फ लिखने के लिए इसे खोलने से परिवर्तित घटना नहीं बढ़ती है। तो यह सुरक्षित होना चाहिए।


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

1
हालांकि यह पूछे गए सवाल का सबसे अच्छा समाधान हो सकता है, लेकिन कुछ टिप्पणियों को जोड़ना हमेशा अच्छा होता है क्योंकि आपने इस दृष्टिकोण को क्यों चुना और आपको लगता है कि यह काम करता है। :)
वाका

1

कब्र खोदने के लिए खेद है, लेकिन मैं अभी कुछ समय के लिए इस मुद्दे से जूझ रहा हूं और अंत में इन कई गोलीबारी की घटनाओं को संभालने का एक तरीका आया हूं। मैं इस धागे में सभी का शुक्रिया अदा करना चाहता हूं क्योंकि मैंने इस मुद्दे से जूझते समय कई संदर्भों में इसका इस्तेमाल किया है।

यहाँ मेरा पूरा कोड है। यह फ़ाइल के अंतिम लिखने की तारीख और समय को ट्रैक करने के लिए एक शब्दकोश का उपयोग करता है। यह उस मूल्य की तुलना करता है, और यदि यह समान है, तो यह घटनाओं को दबा देता है। यह तब नया थ्रेड प्रारंभ करने के बाद मान सेट करता है।

using System.Threading; // used for backgroundworker
using System.Diagnostics; // used for file information
private static IDictionary<string, string> fileModifiedTable = new Dictionary<string, string>(); // 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<object> arguments = new List<object>();

                            // 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" );
        }
    }

यह मेरी एक परियोजना में इस्तेमाल किया। बहुत अच्छा काम करता है!
टायलर मोंटनी

के रूप में काम नहीं किया घटनाओं को अलग कर रहे हैं अलग हैं: अंतिम लिखें समय: 636076274162565607 अंतिम समय लिखें: 636076274162655722
को प्रोग्रामिंग

1

इवेंट अगर नहीं पूछा जाता है, तो यह शर्म की बात है कि एफ # के लिए कोई तैयार समाधान के नमूने नहीं हैं। इसे ठीक करने के लिए यहाँ मेरा नुस्खा है, सिर्फ इसलिए कि मैं कर सकता हूँ और एफ # एक अद्भुत .NET भाषा है।

नकली घटनाओं को FSharp.Control.Reactiveपैकेज का उपयोग करके फ़िल्टर किया जाता है, जो प्रतिक्रियाशील एक्सटेंशन के लिए सिर्फ एफ # आवरण है। उन सभी को पूर्ण रूपरेखा के लिए लक्षित किया जा सकता है या 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

[<EntryPoint>]
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

1

मेरे मामले में एक पाठ फ़ाइल की अंतिम पंक्ति प्राप्त करने की आवश्यकता है जो कि अन्य एप्लिकेशन द्वारा डाली जाती है, जैसे ही प्रविष्टि होती है। यहाँ मेरा समाधान है। जब पहली घटना को उठाया जाता है, तो मैं द्रष्टा को दूसरों को ऊपर उठाने से अक्षम करता हूं, फिर मैं टाइमर को टाइमप्लेस्डइनवेंट कहता हूं क्योंकि जब मेरे हैंडल फ़ंक्शन को ऑनचेंज कहा जाता है, तो मुझे पाठ फ़ाइल के आकार की आवश्यकता होती है, लेकिन उस समय का आकार वास्तविक आकार नहीं है, यह प्रविष्टि से पहले फ़ाइल imediatelly का आकार है। इसलिए मैं सही फ़ाइल आकार के साथ आगे बढ़ने के लिए थोड़ी देर प्रतीक्षा करता हूं।

private FileSystemWatcher watcher = new FileSystemWatcher();
...
watcher.Path = "E:\\data";
watcher.NotifyFilter = NotifyFilters.LastWrite ;
watcher.Filter = "data.txt";
watcher.Changed += new FileSystemEventHandler(OnChanged);
watcher.EnableRaisingEvents = true;

...

private void OnChanged(object source, FileSystemEventArgs e)
   {
    System.Timers.Timer t = new System.Timers.Timer();
    try
    {
        watcher.Changed -= new FileSystemEventHandler(OnChanged);
        watcher.EnableRaisingEvents = false;

        t.Interval = 500;
        t.Elapsed += (sender, args) => t_Elapsed(sender, e);
        t.Start();
    }
    catch(Exception ex) {
        ;
    }
}

private void t_Elapsed(object sender, FileSystemEventArgs e) 
   {
    ((System.Timers.Timer)sender).Stop();
       //.. Do you stuff HERE ..
     watcher.Changed += new FileSystemEventHandler(OnChanged);
     watcher.EnableRaisingEvents = true;
}

1

यह कोशिश करो, यह ठीक काम कर रहा है

  private static readonly FileSystemWatcher Watcher = new FileSystemWatcher();
    static void Main(string[] args)
    {
        Console.WriteLine("Watching....");

        Watcher.Path = @"D:\Temp\Watcher";
        Watcher.Changed += OnChanged;
        Watcher.EnableRaisingEvents = true;
        Console.ReadKey();
    }

    static void OnChanged(object sender, FileSystemEventArgs e)
    {
        try
        {
            Watcher.Changed -= OnChanged;
            Watcher.EnableRaisingEvents = false;
            Console.WriteLine($"File Changed. Name: {e.Name}");
        }
        catch (Exception exception)
        {
            Console.WriteLine(exception);
        }
        finally
        {
            Watcher.Changed += OnChanged;
            Watcher.EnableRaisingEvents = true;
        }
    }

1

मैं केवल अंतिम घटना पर प्रतिक्रिया करना चाहता था, बस मामले में, एक लिनक्स फ़ाइल परिवर्तन पर भी ऐसा लगता था कि फ़ाइल पहले कॉल पर खाली थी और फिर अगले पर फिर से भर गई और बस ओएस के मामले में कुछ समय खोने का मन नहीं किया कुछ फ़ाइल / विशेषता परिवर्तन करने का निर्णय लिया गया।

मैं थ्रेडिंग करने में मेरी मदद करने के लिए यहां .NET async का उपयोग कर रहा हूं।

    private static int _fileSystemWatcherCounts;
    private async void OnChanged(object sender, FileSystemEventArgs e)
    {
        // Filter several calls in short period of time
        Interlocked.Increment(ref _fileSystemWatcherCounts);
        await Task.Delay(100);
        if (Interlocked.Decrement(ref _fileSystemWatcherCounts) == 0)
            DoYourWork();
    }

1

मुझे लगता है कि समस्या को हल करने के लिए सबसे अच्छा समाधान प्रतिक्रियाशील एक्सटेंशन का उपयोग करना है जब आप घटना को अवलोकनीय में बदलते हैं, तो आप बस थ्रॉटलिंग (..) जोड़ सकते हैं (मूल रूप से डिब्यूज़ (..) कहा जाता है)

यहाँ नमूना कोड

        var templatesWatcher = new FileSystemWatcher(settingsSnapshot.Value.TemplatesDirectory)
        {
            NotifyFilter = NotifyFilters.LastWrite,
            IncludeSubdirectories = true
        };

        templatesWatcher.EnableRaisingEvents = true;

        Observable.FromEventPattern<FileSystemEventHandler, FileSystemEventArgs>(
                addHandler => templatesWatcher.Changed += addHandler,
                removeHandler => templatesWatcher.Changed -= removeHandler)
            .Throttle(TimeSpan.FromSeconds(5))
            .Subscribe(args =>
            {
                _logger.LogInformation($"Template file {args.EventArgs.Name} has changed");
                //TODO do something
            });

0

मैं एक फ़ंक्शन जोड़कर ऐसा करने में सक्षम था जो एक बफर सरणी में डुप्लिकेट के लिए जांच करता है।

फिर एक्स टाइमर का उपयोग करके एक्स समय के लिए संशोधित नहीं किए जाने के बाद फिर कार्रवाई करें: - हर बार कुछ बफर को लिखे जाने पर टाइमर रीसेट करें - टिक पर कार्रवाई करें

यह एक और दोहराव प्रकार भी पकड़ता है। यदि आप किसी फ़ोल्डर के अंदर एक फ़ाइल को संशोधित करते हैं, तो फ़ोल्डर एक चेंज ईवेंट भी फेंकता है।

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
<Extension()>
Public Function parentDir(ByVal aString As String) As String
    Return aString.Substring(0, CInt(InStrRev(aString, "\", aString.Length - 1)))
End Function
End Module

0

इस समाधान ने मेरे लिए उत्पादन अनुप्रयोग पर काम किया:

वातावरण:

VB.Net फ्रेमवर्क 4.5.2

मैन्युअल रूप से ऑब्जेक्ट गुण सेट करें: NotifyFilter = Size

फिर इस कोड का उपयोग करें:

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

यह @ जैमी क्रैमर जैसी ही अवधारणा का उपयोग करता है लेकिन VB.NET के लिए
wpcoder

0

इसे इस्तेमाल करे!

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

}

0

मुझे ऊपर के पदों से कई विचारों को जोड़ना था और इसे मेरे लिए काम करने के लिए फ़ाइल लॉकिंग चेक जोड़ना था:

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<String> 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<String, DateTime> DirectoryWatcher_fileLastWriteTimeCache = new Dictionary<String, DateTime>();

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

0

मैंने इस तरह डबल क्रिएट इश्यू के लिए संपर्क किया, जो पहली घटना को नजरअंदाज करता है:

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
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.