Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/260.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/joomla/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何确定文件夹是否已完成复制c#_C#_.net_Directory_Filesystemwatcher - Fatal编程技术网

如何确定文件夹是否已完成复制c#

如何确定文件夹是否已完成复制c#,c#,.net,directory,filesystemwatcher,C#,.net,Directory,Filesystemwatcher,我有一个问题:如何确定文件夹是否已完成从一个位置到另一个位置的复制 目前,只要复制目录中的文件,我的FileSystemWatcher就会触发几个事件。不过,我想要的是,当成功复制该文件夹中的所有文件时触发一个事件。我现在的代码如下所示: static void Main(string[] args) { String path = @"D:\Music"; FileSystemWatcher mWatcher = new FileSystemWatche

我有一个问题:如何确定文件夹是否已完成从一个位置到另一个位置的复制

目前,只要复制目录中的文件,我的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不会告诉您文件何时完成写入。所以你的选择是

  • 在上次写入之后设置一个超时时间,假设没有更多的更改
  • 让编写应用程序放入某种类型的锁文件,告诉任何其他程序它已经完成了
  • 在重读你的问题之后。。。听起来您对其他应用程序没有任何控制权

    因此,您需要某种类型的超时值来确定何时完成所有写入。基本上创建一个计时器,在每个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,并注册创建和更改的事件,包装它们,并在文件完成后抛出自己创建和更改的事件,类似于:

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

    其中一些是从答案中得出的。实际上,不应该使用无限循环。您可能希望添加超时、在检查之间休眠等,但这是一般的想法。

    如果目标是本地文件夹,您可以使用文件系统筛选器驱动程序跟踪文件创建和文件关闭事件。知道以前创建的所有文件何时关闭将通知您复制已完成。

    我创建了一个Git repo,其中包含一个类,该类扩展了
    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();
            }
        }
    

    注意网络位置,FSW不擅长监控这些位置。