ফাইল-সিস্টেম ওয়াটারের পরিবর্তিত ইভেন্টটি দু'বার উত্থাপিত হয়


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
@ ব্রিটআরগবি: অবাক হওয়ার কিছু নেই। এই সম্ভাব্য উত্তরগুলির কোনওটিই সমস্যার সমাধান সরবরাহ করে না। এগুলি নির্দিষ্ট সমস্যাগুলির জন্য সমস্ত কাজের ক্ষেত্র। আসলে, তাদের কেউই আমার নির্দিষ্ট সমস্যা সমাধান করেনি (আমাকে অবশ্যই স্বীকার করতে হবে, আমি তাদের সবকটি পরীক্ষা করে দেখিনি)।

এটি একটি workaround, কিন্তু এটি workaround মানের দ্বারা বিচার করা উচিত। পরিবর্তনগুলি ট্র্যাক করা নিখুঁতভাবে কাজ করে এবং এটি সহজ। ওপি সদৃশ ইভেন্টগুলিকে দমন করার জন্য একটি উপায় চাইছে এবং নীচের প্রতিক্রিয়াগুলি সেটাই দেয়। msdn.microsoft.com/en-us/library/… ব্যাখ্যা করে যে একাধিক ইভেন্ট অ্যান্টি-ভাইরাস, বা অন্যান্য "জটিল ফাইল সিস্টেম স্টাফ" (যা কেবল একটি অজুহাত বলে মনে হয়) এর কারণে ঘটতে পারে।
টাইলার মন্টনি

2
আমি সম্প্রতি এই সমস্যাটি প্রকাশ করেছি github.com/Mic Microsoft
স্টিফান আহল্ফ

2
আমি একটি ক্লাস তৈরি করেছি যা আপনাকে কেবল একটি ইভেন্ট পেতে সহায়তা করে। আপনি github.com/melenaos/FileSystemSafeWatcher
মেনেলাওস ভার্জিস

উত্তর:


276

আমি ভয় পাচ্ছি যে এটি FileSystemWatcherক্লাসের একটি সুপরিচিত বাগ / বৈশিষ্ট্য । এটি শ্রেণীর নথি থেকে:

আপনি নির্দিষ্ট পরিস্থিতিতে লক্ষ্য করতে পারেন যে একটি একক সৃষ্টি ইভেন্ট আপনার উপাদান দ্বারা পরিচালিত একাধিক তৈরি ইভেন্ট উত্পন্ন করে। উদাহরণস্বরূপ, আপনি যদি কোনও ডিরেক্টরিতে নতুন ফাইল তৈরির বিষয়টি পর্যবেক্ষণ করার জন্য কোনও ফাইলসিসটেমওয়াচার উপাদান ব্যবহার করেন এবং ফাইলটি তৈরির জন্য নোটপ্যাড ব্যবহার করে এটি পরীক্ষা করেন তবে কেবল দুটি একটি ইভেন্ট তৈরি করা সত্ত্বেও আপনি দুটি উত্পন্ন ইভেন্ট দেখতে পেতে পারেন। কারণ নোটপ্যাড লিখন প্রক্রিয়া চলাকালীন একাধিক ফাইল সিস্টেম ক্রিয়া করে। নোটপ্যাড ব্যাচগুলির ডিস্কে লেখেন যা ফাইলের সামগ্রী এবং তারপরে ফাইলের বৈশিষ্ট্য তৈরি করে। অন্যান্য অ্যাপ্লিকেশন একই পদ্ধতিতে সঞ্চালন করতে পারে। যেহেতু ফাইলসিস্টেমওয়াটার অপারেটিং সিস্টেমের ক্রিয়াকলাপগুলি নিরীক্ষণ করে, সমস্ত অ্যাপ্লিকেশন যা এই অ্যাপ্লিকেশনগুলিতে ব্যবহৃত হয় সেগুলি তুলে নেওয়া হবে।

এখন এই বিট পাঠটি Createdইভেন্টটি সম্পর্কে , তবে একই জিনিসটি অন্যান্য ফাইল ইভেন্টগুলিতেও প্রযোজ্য। কিছু অ্যাপ্লিকেশনগুলিতে আপনি এটি ব্যবহার করে এটি ঘিরে রাখতে সক্ষম হতে পারেনNotifyFilter সম্পত্তিটি তবে আমার অভিজ্ঞতাটি বলে যে কখনও কখনও আপনাকে কিছু ম্যানুয়াল ডুপ্লিকেট ফিল্টারিং (হ্যাক) করতে হয়।

কিছুক্ষণ আগে আমি কয়েকটি ফাইল-সিস্টেম ওয়াটার টিপস সহ একটি পৃষ্ঠা বুকমার্ক করেছি । আপনি এটি পরীক্ষা করে দেখতে চাইবেন।



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
কয়েক মাস কেটে গেছে তবে আমি মনে করি আমি কী করে শেষ করেছি ইভেন্টটি এমন একটি পদ্ধতি কল করে যা ব্যবসায়ের লজিককে একটি লক স্টেটমেন্টের ভিতরে রাখে। এইভাবে যদি আমি অতিরিক্ত ইভেন্টগুলি পাই তবে তারা তাদের পালা না হওয়া পর্যন্ত সারিবদ্ধভাবে দাঁড়িয়ে আছে এবং পূর্ববর্তী পুনরাবৃত্তি সমস্ত কিছুর যত্ন নিয়েছে বলে তাদের করার কিছুই নেই nothing
ক্রিস্টোফার পেইন্টার

15
এটি সমস্যা সমাধানের জন্য উপস্থিত হয়, তবে তা হয় না। যদি অন্য কোনও প্রক্রিয়া পরিবর্তন করে থাকে তবে আপনি সেগুলি হারাতে পারেন, এটির কাজটি প্রদর্শিত হওয়ার কারণ হ'ল অন্য প্রক্রিয়ার আইও হ'ল এসিঙ্ক, এবং আপনি আপনার প্রসেসিং সম্পন্ন না করা অবধি নিরীক্ষণ অক্ষম করে রেখেছেন, এইভাবে অন্যান্য ইভেন্টগুলির সাথে রেস শর্ত তৈরি করে be সুদ. এই কারণেই @ ক্রিসটফারপেন্টার তাঁর বিষয়টি পর্যবেক্ষণ করেছেন।
জেফ Beaulac

14
-1: অক্ষম থাকাকালীন আপনি যদি আগ্রহী অন্য একটি পরিবর্তন ঘটে তবে কী হবে?
জি স্টোনেভ

2
@ ইউনিস: আপনি যদি আপনার জিনিসগুলি তত্ক্ষণিকভাবে না করেন ।
ডেভিড ব্র্যাব্যান্ট

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
আমি সেই সমাধানটি পছন্দ করি, তবে আমি "ডান" জিনিসটি "Rename"করতে Observable.FromEventPattern<FileSystemEventArgs>(fileSystemWatcher, "Renamed") .Select(e => e.EventArgs) .Distinct(e => e.FullPath) .Subscribe(onNext);
আরএক্স

4
আমি কিছু অনুপস্থিত করছি? আমি বুঝতে পারি না এটি কীভাবে কাজ করবে। ইভেন্টগুলি একই সাথে আগুন দেখেছি তাই তারা যদি উভয় একই সময়ে উপরের ইভেন্টে প্রবেশ করে তবে তারা উভয়ই সর্বশেষেড সেট হওয়ার আগেই চলতে শুরু করবে।
পিটার জামসেমসন

যেহেতু DateTimeকেবলমাত্র মিলিসেকেন্ড রেজোলিউশন রয়েছে, আপনি যদি প্রতিস্থাপন করেন এমনকি এই পদ্ধতিটি কাজ File.GetLastWriteTimeকরে DateTime.Now। আপনার পরিস্থিতির উপর নির্ভর করে a.FullNameডুপ্লিকেট ইভেন্টগুলি সনাক্ত করতে আপনি বৈশ্বিক পরিবর্তনশীলটি ব্যবহার করতে পারেন ।
রোল্যান্ড

@ পিটারজ্যামসনসন ঘটনাগুলি একইসাথে আগুন দেয় না। উদাহরণস্বরূপ, ডিস্কে পরিবর্তনগুলি সংরক্ষণ করার সময় নোটপ্যাড বেশ কয়েকটি ইভেন্ট তৈরি করতে পারে তবে নোটপ্যাডকে সেভ করার জন্য সঞ্চালনের জন্য প্রয়োজনীয় কয়েকটি পদক্ষেপের সময় এই ঘটনাগুলি একের পর এক নষ্ট করা হয়। বাবুর পদ্ধতি দুর্দান্ত কাজ করে।
রোল্যান্ড

10
ঘটনাগুলি গুলি ছড়িয়ে দেওয়া ঘটনাগুলি টিকিয়ে রাখার মতো কাজ করে না: শেষ লেখার সময়: 636076274162565607 শেষ লেখার সময়: 636076274162655722
আশেহ

23

এখানে আমার সমাধান যা ইভেন্টটিকে দু'বার উত্থাপিত করা বন্ধ করতে সহায়তা করেছিল:

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

এখানে আমি NotifyFilterকেবল ফাইলের নাম এবং আকার দিয়ে সম্পত্তি সেট করেছি ।
watcherফাইলসিস্টেমওয়াটারের আমার অবজেক্ট। আশা করি এটি সাহায্য করবে।


9
এছাড়াও, নোটপ্যাডে, আমি চারটি অক্ষর সহ একটি ফাইল তৈরি করেছি: এতে abcd। আমি তখন নোটপ্যাডের একটি নতুন উদাহরণ খুললাম এবং একই চারটি অক্ষরে প্রবেশ করলাম। আমি ফাইল | হিসাবে সংরক্ষণ করুন এবং একই ফাইলটি চয়ন করেছেন। ফাইলটি অভিন্ন এবং আকার এবং ফাইলের নাম পরিবর্তন হয় না, যেহেতু ফাইলটির একই চারটি বর্ণ রয়েছে, সুতরাং এটি আগুন দেয় না।
ছড়া

30
এটি সম্ভব যে একটি আসল পরিবর্তন করা যেতে পারে যা ফাইলের আকার পরিবর্তন করে না, সুতরাং এই কৌশলটি সেই পরিস্থিতিতে ব্যর্থ হবে।
লি গ্রিসম

3
আমি অনুমান করব এটি একটি মোটামুটি সাধারণ ঘটনা যেখানে আপনি জানেন যে কোনও অর্থবহ পরিবর্তন ফাইলের আকার পরিবর্তন করবে (উদাহরণস্বরূপ, আমার কেস লগ ফাইলটিতে সংযোজন করছিল)। যে কেউ এই সমাধানটি ব্যবহার করেন সে সম্পর্কে (এবং নথি) এই ধারণাটি সম্পর্কে সচেতন হওয়া উচিত, এটি আমার প্রয়োজন ঠিক ঠিক ছিল।
গ্র্যান্ডঅপনার

1
@ গ্র্যান্ডওপেনার: এটি সর্বদা সত্য নয়। আমার ক্ষেত্রে আমি ফাইলগুলি দেখছি যেখানে এর সামগ্রীতে কেবলমাত্র একটি অক্ষর রয়েছে যা হয় হয় 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
স্ট্রিংগুলির তুলনা করবেন না, ডেটটাইম.এক্কুলস () ব্যবহার করুন
ফিলিপ কামিকাজে

না, না। তারা সমান নয়। আমার বর্তমান প্রকল্পের ক্ষেত্রে, তারা প্রায় এক মিলি সেকেন্ডের ব্যবধানে। আমি (নিউটাইম-ওল্ডটাইম) ব্যবহার করি .টোটালমিলিসেকেন্ডস (স্বেচ্ছাসেবী প্রান্তিকর, সাধারণত 5 মিমি)।
ফ্লাইএন 1179

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
এটি সেরা সমাধান, একটি টাইমার পরিবর্তে একটি semaphore ব্যবহার করে।
অ্যারন ব্লেনকুশ

1
কি সেমফোর? আমি এখানে একটি বুলিয়ান পরিবর্তনশীল দেখতে পাচ্ছি। তদ্ব্যতীত, মূল সমস্যাটি সমাধান করা হয় না: ফাইলসিস্টেমএভেন্টহ্যান্ডলার এখনও একাধিক ইভেন্টে গুলি চালাচ্ছে। এবং এই কোডটির কার্যকারিতা কী? if (let==false) { ... } else { let = false; }? এটি কীভাবে উত্সাহ পেয়েছে তা অবিশ্বাস্য, এটি কেবল স্ট্যাকওভারফ্লো ব্যাজগুলির বিষয় হতে হবে।
সুনুন ןɐ কিউপি

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 বার্তা সহ মেইলবক্সটি বন্যার চেয়ে কিছু পরিবর্তন অনুপস্থিত থেকে বেশি খুশি হয়েছিলাম। সঠিক সময়ে একই সাথে বেশ কয়েকটি ফাইল পরিবর্তিত হওয়ার ক্ষেত্রে এটি ঠিক কাজ করে।

আমি যে অন্য সমাধানের কথা ভেবেছি তা হ'ল তালিকার ম্যাপিং ফাইলগুলিকে তাদের নিজ নিজ MD5 এ তালিকাটি প্রতিস্থাপন করা হবে, সুতরাং আপনাকে এন্ট্রি বিভাজন বেছে নিতে হবে না কারণ আপনাকে এন্ট্রি মুছতে হবে না তবে এর মান আপডেট করতে হবে, এবং আপনার স্টাফ পরিবর্তন না হলে এটি বাতিল করুন। ফাইলগুলি পর্যবেক্ষণ করা এবং আরও বেশি মেমরি খাওয়ার ফলে এটি মেমোরিয় একটি ডিকশনারি বৃদ্ধির খারাপ দিক রয়েছে তবে আমি কোথাও পড়েছি যে মনিটরি করা ফাইলগুলির পরিমাণ FSW এর অভ্যন্তরীণ বাফারের উপর নির্ভরশীল, তাই সম্ভবত এটি সমালোচনা নয়। ডুনো কীভাবে এমডি 5 কম্পিউটিং সময়টি আপনার কোডের পারফরম্যান্সগুলিকে প্রভাবিত করবে, সতর্কতা = \


আপনার সমাধানটি আমার পক্ষে দুর্দান্ত কাজ করে। কেবলমাত্র, আপনি _ চেঞ্জড ফাইলস তালিকায় ফাইল যুক্ত করতে ভুলে গেছেন। lock (_changedFiles) { if (_changedFiles.Contains(e.FullPath)) { return; } _changedFiles.Add(e.FullPath); // add this! } // do your stuff
কোডটির

আমি উপরে 4 টি উত্তর কমিয়ে দিয়েছি এবং এটি উত্তর দিয়েছি। আপনার উত্তরটি হ'ল প্রথমটি নয় বরং সর্বশেষ ইভেন্টটি গ্রহণ করে প্রথমে এটি করা উচিত। @ জর্ন দ্বারা ব্যাখ্যা করা হয়েছে যে সমস্যাগুলি হ'ল ফাইলগুলি ব্যাচে লেখা থাকে। অন্যান্য সমাধানগুলি আমার পক্ষে কার্যকর হয়নি।
কোডিংইউরলাইফ

আপনার সমাধান থ্রেড-নিরাপদ নয়। _changedFilesএকাধিক থ্রেড থেকে অ্যাক্সেস করা হয়। এটির সমাধানের একটি উপায় ConcurrentDictionaryপরিবর্তে একটি ব্যবহার করা List। আরেকটি উপায় বর্তমান দায়িত্ব অর্পণ করা হয় Formথেকে Timer.SynchronizingObject, সম্পত্তি হিসাবে ভাল হিসাবে FileSystemWatcher.SynchronizingObjectসম্পত্তি।
থিওডর জৌলিয়াস

5

আমি একটি ক্লাস সহ একটি গিট রেপো তৈরি করেছি যা অনুলিপিগুলি FileSystemWatcherসম্পন্ন করা হলেই ইভেন্টগুলি ট্রিগার করতে প্রসারিত । এটি সমস্ত পরিবর্তিত ইভেন্টগুলি সর্বশেষে উপস্থিতিকে ছাড়িয়ে যায় এবং এটি কেবল তখনই উত্থাপন করে যখন ফাইলটি পড়ার জন্য উপলব্ধ হয়।

ফাইলসিস্টেমস্যাফওয়্যাচার ডাউনলোড করুন এবং এটি আপনার প্রকল্পে যুক্ত করুন।

তারপরে এটিকে সাধারণ হিসাবে ব্যবহার করুন FileSystemWatcherএবং ইভেন্টগুলি ট্রিগার করা হলে মনিটর করুন।

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

কোনও ইভেন্ট ডিরেক্টরিতে উত্থাপিত হওয়ার পরে এটি ব্যর্থ হয় বলে মনে হয়। আমি ফাইলটি খোলার আগে ডিরেক্টরি চেক মোড়ক দিয়ে কাজ করতে পেরেছি
স্যাম

উদাহরণে টাইপো সত্ত্বেও এটি আমার পক্ষে একটি কার্যকর সমাধান বলে মনে হয়। তবে, আমার ক্ষেত্রে এক সেকেন্ডের মধ্যে কয়েক ডজন আপডেট হতে পারে, সুতরাং কোনও পরিবর্তন মিস না করার জন্য আমাকে কঠোরভাবে _ সংবিধানসংক্ষেপটি হ্রাস করতে হয়েছিল। যদিও 10 এমএস ঠিক আছে বলে মনে হচ্ছে আমি এখনও যদি প্রায় 50% আপডেটগুলি সীমাবদ্ধ রাখি তবে আমি 50% আপডেট আপডেট করে _ মানটি সর্বাধিক মানানসই করতে আমাকে এখনও কিছু পরীক্ষা চালাতে হবে।

_ সংবিধান অন্তর্বর্তীকাল আমার পক্ষে ভাল কাজ করছে বলে মনে হচ্ছে। আমি চাই যে কেউ এটিকে কাঁটাচামচ করুন এবং এটিকে একটি নুগেট প্যাকেজ তৈরি করুন।
জুমালাইফগার্ড

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);
ডায়মন্ডড্রেক

আমার পক্ষে কাজ করেনি। আমার চেঞ্জ হ্যান্ডলারটি দু'বার কল করা হয়েছে এবং দ্বিতীয়বার ফাইলটির আলাদা টাইমস্ট্যাম্প রয়েছে। হতে পারে কারণ এটি একটি বড় ফাইল এবং লেখার কাজটি প্রথমবারের মতো চলছে। সদৃশ ইভেন্টগুলি আরও ভাল কাজ করার জন্য আমি একটি টাইমার পেয়েছি।
মাইকেল 25

3

সম্ভাব্য একটি 'হ্যাক' হ'ল উদাহরণস্বরূপ প্রতিক্রিয়াশীল এক্সটেনশনগুলি ব্যবহার করে ইভেন্টগুলি থ্রোট করা:

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

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

watcher.EnableRaisingEvents = true;

এক্ষেত্রে আমি আমার সিস্টেমে 50 মিমি পর্যন্ত থ্রোটল করছি যা যথেষ্ট ছিল তবে উচ্চতর মানগুলি আরও নিরাপদ হওয়া উচিত। (এবং যেমনটি আমি বলেছিলাম, এটি এখনও একটি 'হ্যাক')।


আমি ব্যবহার করেছি .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

যদিও এটি পরীক্ষা না করে, আমি নিশ্চিত না যে এটি তৈরি এবং মুছে ফেলার জন্য কাজ করে না। এটি তাত্ত্বিকভাবেও প্রযোজ্য হওয়া উচিত the ফায়ারকাউন্ট ++ এবং যদি () বিবৃতি উভয়ই পারমাণবিক হয় এবং অপেক্ষা করতে হবে না। এমনকি দুটি ট্রিগারযুক্ত ইভেন্ট একে অপরের সাথে প্রতিযোগিতা করে। আমার ধারণা আপনার ঝামেলার কারণ অবশ্যই আছে something (হারিয়েছেন? কী বোঝাতে চেয়েছেন?)
জিয়াওউভাক্স

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;সঠিক জিনিস করা উচিত।
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

আমি ফাইলসিস্টেমওয়াটার ব্যবহার করে কিছু উল্লেখযোগ্য পরিমাণ সময় ব্যয় করেছি এবং এখানে কিছু পদ্ধতির কাজ করবে না। আমি সত্যিই অক্ষম করার ইভেন্টগুলির পদ্ধতির পছন্দ করেছি, তবে দুর্ভাগ্যক্রমে,> 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

বেশিরভাগ ক্ষেত্রে ভবিষ্যতের জন্য :)

আমি আরএক্স ব্যবহার করে একটি মোড়ক লিখেছিলাম:

 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

ডিরেক্টরিগুলিতে ফাইলগুলি নিরীক্ষণের পদ্ধতিটি আমি বদলেছি। ফাইলসিস্টেমওয়াটার ব্যবহারের পরিবর্তে আমি অন্য থ্রেডে অবস্থানগুলি পোল করে এবং তারপরে ফাইলটির লাস্ট রাইটটাইমটি দেখুন।

DateTime lastWriteTime = File.GetLastWriteTime(someFilePath);

এই তথ্যটি ব্যবহার করে এবং কোনও ফাইলের পথের একটি সূচক রেখেছি এবং সর্বশেষ লেখার সময় আমি ফাইলগুলি নির্দিষ্ট করতে পারি যা পরিবর্তিত হয়েছে বা কোনও নির্দিষ্ট স্থানে নির্মিত হয়েছে। এটি আমাকে ফাইলসিস্টেমওয়াটারের প্রতিকূলতা থেকে সরিয়ে দেয়। প্রধান খারাপ দিকটি হ'ল লাস্ট রাইটটাইম এবং ফাইলটির রেফারেন্স সংরক্ষণ করার জন্য আপনার একটি ডেটা কাঠামো প্রয়োজন তবে এটি নির্ভরযোগ্য এবং কার্যকর করা সহজ।


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
যদিও এটি জিজ্ঞাসিত প্রশ্নের সেরা সমাধান হতে পারে তবে আপনি কেন এই পদ্ধতির পছন্দ করেছেন এবং কেন এটি আপনার কাজ করে বলে মনে হয় সে সম্পর্কে কিছু মন্তব্য যুক্ত করে সর্বদা ভাল। :)
Waka

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

ইভেন্ট যদি না জিজ্ঞাসা করা হয় তবে এটি লজ্জার বিষয় যে এফ # এর জন্য প্রস্তুত সমাধানের নমুনা নেই। এটি ঠিক করার জন্য আমার রেসিপিটি হ'ল কেবলমাত্র আমি এবং F # একটি দুর্দান্ত। নেট ভাষা।

সদৃশ ইভেন্টগুলি FSharp.Control.Reactiveপ্যাকেজ ব্যবহার করে ফিল্টার করা হয় যা প্রতিক্রিয়াশীল এক্সটেনশনের জন্য কেবল একটি F # র‍্যাপার। সম্পূর্ণ ফ্রেমওয়ার্ক বা লক্ষ্য 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

আমার ক্ষেত্রে একটি পাঠ্য ফাইলের শেষ লাইনটি পাওয়া দরকার যা সন্নিবেশ সম্পন্ন হওয়ার সাথে সাথে অন্যান্য অ্যাপ্লিকেশন দ্বারা সন্নিবেশ করা হয়। এখানে আমার সমাধান। যখন প্রথম ইভেন্টটি উত্থাপিত হয়, আমি অন্যকে উত্থাপন থেকে নজরদারিটিকে অক্ষম করি, তারপরে আমি টাইমারকে টাইমএলপসিড এভেন্ট বলি কারণ যখন আমার হ্যান্ডেল ফাংশন অনচেনজড বলা হয় তখন আমাকে পাঠ্য ফাইলের আকার প্রয়োজন হয়, তবে সেই সময়কার আকারটি প্রকৃত আকার নয়, সন্নিবেশের আগে এটি ফাইলের আকার থেকে নির্ধারিত হয়। তাই আমি সঠিক ফাইলের আকার নিয়ে এগিয়ে যাওয়ার জন্য কিছুক্ষণ অপেক্ষা করি।

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

আমি কেবলমাত্র শেষ ইভেন্টে প্রতিক্রিয়া জানাতে চেয়েছিলাম, ঠিক এক্ষেত্রে, একটি লিনাক্স ফাইল পরিবর্তনের ক্ষেত্রেও মনে হয়েছিল যে ফাইলটি প্রথম কলটিতে খালি ছিল এবং তারপরে আবার পূরণ করা হয়েছিল এবং ওএসের ক্ষেত্রে কিছুটা সময় হারাতে আপত্তি নেই did কিছু ফাইল / বৈশিষ্ট্য পরিবর্তন করার সিদ্ধান্ত নিয়েছে।

থ্রেডিং করতে আমাকে সহায়তা করতে আমি এখানে নেট নেট অ্যাসিঙ্ক ব্যবহার করছি।

    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

এই সমাধানটি উত্পাদন অ্যাপ্লিকেশন সম্পর্কে আমার জন্য কাজ করেছে:

পরিবেশ:

ভিবি.নেট ফ্রেমওয়ার্ক 4.5.2

ম্যানুয়ালি অবজেক্ট বৈশিষ্ট্য সেট করুন: নোটিফাইফিল্টার = আকার

তারপরে এই কোডটি ব্যবহার করুন:

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

এটি @ জ্যামি ক্রিকমার মতো একই ধারণা ব্যবহার করে তবে ভিবি.এনইটি
ডব্লিউপিপোডার 16

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
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.