سؤال

لدي ملف filesystemWatcher الذي سيؤدي إلى حدث حدث عند تعديل ملف. أريد أن أقرأ من هذا الملف بمجرد إزالة القفل. في الوقت الحالي، أحاول فقط فتح الملف بمجرد تشغيل الحدث، عندما يتم نسخ ملف كبير من قفل الملفات بإقامه لفترة من الوقت بعد أن تم إرسال الأحداث، منع فتح الملف من الوصول إليه للقراءة.

أي اقتراحات؟

هل كانت مفيدة؟

المحلول

هذا الشخص في الواقع قليلا من Doozie، ما لم تتغير مساحة المشكلة بشكل كبير منذ أن أتعامل معها.

أسهل طريقة هي ببساطة محاولة فتح الملف، والقبض على الناتجة IOException, ، وإذا تم تأمين الملف، أضفه إلى قائمة انتظار للتحقق في وقت لاحق. لا يمكنك فقط محاولة معالجة كل ملف يأتي نظرا لأن هناك جميع أنواع الحالات التي سيتم فيها إنشاء أحداث متعددة لنفس الملف، لذا فإن إعداد حلقة إعادة المحاولة على كل حدث واحد مستلم يمكن أن يتحول إلى كارثة، بسرعة. تحتاج إلى قائمة انتظارهم بدلا من ذلك وتحقق من قائمة الانتظار في فاصل منتظم.

فيما يلي قالب فئة أساسية يجب أن يساعدك في الخروج بهذه المشكلة:

public class FileMonitor : IDisposable
{
    private const int PollInterval = 5000;

    private FileSystemWatcher watcher;
    private HashSet<string> filesToProcess = new HashSet<string>();
    private Timer fileTimer;  // System.Threading.Timer

    public FileMonitor(string path)
    {
        if (path == null)
            throw new ArgumentNullException("path");

        watcher = new FileSystemWatcher();
        watcher.Path = path;
        watcher.NotifyFilter = NotifyFilters.FileName;
        watcher.Created += new FileSystemEventHandler(FileCreated);
        watcher.EnableRaisingEvents = true;

        fileTimer = new Timer(new TimerCallback(ProcessFilesTimer),
            null, PollInterval, Timeout.Infinite);
    }

    public void Dispose()
    {
        fileTimer.Dispose();
        watcher.Dispose();
    }

    private void FileCreated(object source, FileSystemEventArgs e)
    {
        lock (filesToProcess)
        {
            filesToProcess.Add(e.FullPath);
        }
    }

    private void ProcessFile(FileStream fs)
    {
        // Your code here...
    }

    private void ProcessFilesTimer(object state)
    {
        string[] currentFiles;
        lock (filesToProcess)
        {
            currentFiles = filesToProcess.ToArray();
        }
        foreach (string fileName in currentFiles)
        {
            TryProcessFile(fileName);
        }
        fileTimer.Change(PollInterval, Timeout.Infinite);
    }

    private void TryProcessFile(string fileName)
    {
        FileStream fs = null;
        try
        {
            FileInfo fi = new FileInfo(fileName);
            fs = fi.OpenRead();
        }
        catch (IOException)
        {
            // Possibly log this error
            return;
        }

        using (fs)
        {
            ProcessFile(fs);
        }

        lock (filesToProcess)
        {
            filesToProcess.Remove(fileName);
        }
    }
}

(ملاحظة - أشير إلى هذا من الذاكرة هنا، لذلك قد لا يكون مثاليا - اسمحوا لي أن أعرف ما إذا كان عربات التي تجرها الدواب.)

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top