簡體   English   中英

如何確定文件夾是否已完成復制C#

[英]How to determine whether a folder has finished copying c#

我有一個問題:如何確定文件夾是否已完成從一個位置到另一個位置的復制?

目前,一旦復制目錄中的文件,我的FileSystemWatcher就會觸發多個事件。 我想要的是,成功復制該文件夾中的所有文件后將觸發一個事件。 我的代碼現在看起來像這樣:

static void Main(string[] args)
    {
        String path = @"D:\Music";
        FileSystemWatcher mWatcher = new FileSystemWatcher();
        mWatcher.Path = path;
        mWatcher.NotifyFilter = NotifyFilters.LastAccess;
        mWatcher.NotifyFilter = mWatcher.NotifyFilter | NotifyFilters.LastWrite;
        mWatcher.NotifyFilter = mWatcher.NotifyFilter | NotifyFilters.DirectoryName;
        mWatcher.IncludeSubdirectories = true;
        mWatcher.Created += new FileSystemEventHandler(mLastChange);
        mWatcher.Changed += new FileSystemEventHandler(mLastChange);

        mWatcher.EnableRaisingEvents = true;
        Console.WriteLine("Watching path: " + path);



        String exit;
        while (true)
        {
               exit = Console.ReadLine();
               if (exit == "exit")
                   break;

        }


    }



    private static void mLastChange(Object sender, FileSystemEventArgs e)
    {
        Console.WriteLine(e.ChangeType + " " + e.FullPath);
    }

不幸的是,FileSystemWatcher不會告訴您文件何時完成寫入。 所以你的選擇是...

  1. 假設沒有更多更改來臨,請在最后一次寫入后設置超時
  2. 讓編寫應用程序放置一個各種各樣的鎖文件,以告訴其他程序它已完成。

重新閱讀您的問題后,聽起來您對其他應用程序沒有任何控制權。

因此,您將需要某種超時值來確定何時完成所有寫入。 基本上創建一個計時器,該計時器在每個filesystemwatcher事件發生后重置...當它超時時,您將觸發一個表明已完成的事件。

這是將其添加到代碼中的方法...

static void Main(string[] args)
{
    Timer.Interval = 5000; // 5 seconds - change to whatever is appropriate
    Timer.AutoReset = false;
    Timer.Elapsed += TimeoutDone;
    String path = @"D:\Music";
    FileSystemWatcher mWatcher = new FileSystemWatcher();
    mWatcher.Path = path;
    mWatcher.NotifyFilter = NotifyFilters.LastAccess;
    mWatcher.NotifyFilter = mWatcher.NotifyFilter | NotifyFilters.LastWrite;
    mWatcher.NotifyFilter = mWatcher.NotifyFilter | NotifyFilters.DirectoryName;
    mWatcher.IncludeSubdirectories = true;
    mWatcher.Created += new FileSystemEventHandler(mLastChange);
    mWatcher.Changed += new FileSystemEventHandler(mLastChange);

    mWatcher.EnableRaisingEvents = true;
    Console.WriteLine("Watching path: " + path);
    Timer.Start();

    String exit;
    while (true)
    {
        exit = Console.ReadLine();
        if (exit == "exit")
            break;

    }
}

private static Timer Timer = new Timer();

private static void TimeoutDone(object source, ElapsedEventArgs e)
{
    Console.WriteLine("Timer elapsed!");
}

private static void mLastChange(Object sender, FileSystemEventArgs e)
{
    Console.WriteLine(e.ChangeType + " " + e.FullPath);
    if (Timer != null)
    {
        Timer.Stop();
        Timer.Start();
    }
}

太俗氣了,但過去我通過為FileSystemWatcher類創建自定義裝飾器來解決此問題。 在內部,它創建一個FileSystemWatcher並注冊Created和Changed事件,包裝它們,並在文件完成后拋出自己的Created和Changed事件,類似於:

private void Watcher_Changed(Object sender, FileSystemEVentArgs e)
    {
        while (true)
        {
            FileStream stream;
            try
            {
                stream = File.Open(e.FullPath, FileMode.Open, FileAccess.ReadWrite, FileShare.None);
                // If this succeeds, the file is finished
                Changed();
            }
            catch (IOException)
            {
            }
            finally
            {
                if (stream != null) stream.Close();
            }
        }
    }

其中一些是從這里的答案中得出的。 實際上,您不應該使用無限循環。 您可能想要添加超時,在兩次檢查之間睡眠,等等,但這是一般的想法。

如果目標是本地文件夾,則可以使用文件系統過濾器驅動程序來跟蹤文件創建文件關閉事件。 知道所有先前創建的文件何時關閉將通知您復制已完成。

我用一個擴展FileSystemWatcher的類創建了一個Git存儲庫,使其僅在復制完成后才觸發事件。

下載FileSystemSafeWatcher並將其添加到您的項目中。

然后將其用作普通的FileSystemWatcher並監視何時觸發事件。

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

不幸的是,還沒有現成的解決方案。 但是我設計了一個簡單的棘手解決方案來觸發(復制完成)事件。

您應該使用計時器。

        FileSystemWatcher fsw = new FileSystemWatcher();
        string fullPath = "";
        DateTime tempTime;
        fsw.Path = @"C:\temp";

        private void startwatching()
        {
            timer1.Start();
        }
        fsw.EnableRaisingEvents = true;
        fsw.Created += Fsw_Created;

        private void Fsw_Created(object sender, FileSystemEventArgs e)
        {
            tempTime = DateTime.Now.AddSeconds(-4);
            fullPath = e.FullPath;
        }

    private void timer1_Tick(object sender, EventArgs e)
    {
        if (fullPath!=string.Empty)
        {
            timer1.Stop();
            if (tempTime >= Directory.GetLastAccessTime(fullPath))
            {
                DirectoryInfo di = new DirectoryInfo(fullPath);
                listBox1.Items.Add("Folder " + di.Name + " finished copying");
                fullPath = string.Empty;
            }
            else
            {
                tempTime = DateTime.Now;
            }
            timer1.Start();
        }
    }

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM