【问题标题】:Renaming files and filesharing (filestream)重命名文件和文件共享(文件流)
【发布时间】:2014-08-13 12:15:29
【问题描述】:

我正在使用文件流访问文件(制作 md5 ComputeHash)。如果我在此期间尝试重命名文件(由于正在访问文件而失败)。到目前为止一切顺利,但是当我在关闭原始文件流后尝试重新打开文件时,我得到了文件在另一个进程中打开的信息。

代码:

using (Stream fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) {
    MD5 md5 = MD5.Create();
    byte[] mymd5computed = md5.ComputeHash(fileStream);
    ......
}
Thread.Sleep(50);

Thread a = new Thread (()=>{(FileStream sourceStream = File.Open(filePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)){....} });

就像我说的,如果在计算 MD5 期间我尝试重命名文件,我会得到文件仍然被锁定的信息。

【问题讨论】:

    标签: c#


    【解决方案1】:

    当您关闭流时,有时不会立即释放对文件的锁定,因此您可以使用其他一些解决方案来等待您再次访问该文件。其中之一在此处解释:http://www.codeproject.com/Tips/164428/C-FileStream-Lock-How-to-wait-for-a-file-to-get-re

    回顾:

    public static void Lock(string path, Action<FileStream> action) {
        var autoResetEvent = new AutoResetEvent(false);
    
        while(true)
        {
            try
            {
                using (var file = File.Open(path,
                                            FileMode.OpenOrCreate,
                                            FileAccess.ReadWrite,
                                            FileShare.Write))
                {
                    action(file);
                    break;
                }
            }
            catch (IOException)
            {
                var fileSystemWatcher =
                    new FileSystemWatcher(Path.GetDirectoryName(path))
                            {
                                EnableRaisingEvents = true
                            };
    
                fileSystemWatcher.Changed +=
                    (o, e) =>
                        {
                            if(Path.GetFullPath(e.FullPath) == Path.GetFullPath(path))
                            {
                                autoResetEvent.Set();
                            }
                        };
    
                autoResetEvent.WaitOne();
            }
        } 
    }
    

    使用示例:

    Lock(@"c:\file",
            (f) =>
                {
                    try
                    {
                        f.Write(buf, 0, buf.Length);
                    }
                    catch(IOException ioe)
                    {
    // handle IOException
                    }
                });
    

    希望对您有所帮助! :)

    【讨论】:

    • 哎呀,这是我最担心的情况。除了在文件操作周围放置一个包装器之外,还有其他可能性吗? (需要在那里重写近 1k 行代码)。
    • 这不是一个理想的情况,但根据我以前的经验,有时你能做的就是这样。不仅您的应用程序可以锁定文件,它也可能在您的通话之间被 AV 锁定,尽管可能性很小。有些人尝试像您一样使用 Thread.Sleep() 来解决锁定问题,但我发现这有点“出乎意料”,因为它可能需要更长的时间才能释放,或者它可能会再次被锁定与此同时。如果您可以忍受更长的 Thread.Sleep,那应该没问题,但不会是 100%。即使您处置和关闭流,FileSystem 也可以保持锁定状态。
    • 我目前正在尝试寻找一种方法来区分“文件仅打开几毫秒,因为关闭仍然需要时间”和“另一个应用程序已打开”(例如有人有文件用word打开)。有什么方法可以告诉我是否是我的应用程序正在执行锁定? (否则我将不得不在那里添加某种超时等待,因为当另一个应用程序打开文件时,用户需要通过异常和消息框知道它才能采取相应的行动)。例如:超时时间最长为 1 秒。
    • stackoverflow.com/a/1121236/1361993 这个答案应该可以帮助您找到使用 handle.exe 的锁定过程,如果这对您来说是例外的话 - 我想如果您解析锁定文件的进程并看到您的应用程序不是那个锁定它,您可以警告用户要终止哪个进程才能继续。
    • Tnx。所以总共有 2 种可能性:a.)使用你的锁变体有/没有检查过程能够通知用户他的一个应用程序打开了文件 b.)在所有操作中只使用 1 个文件句柄并且不要关闭它(在这种情况下,如果它已经打开,则该打开必须来自不同的应用程序)。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-09-09
    • 1970-01-01
    • 1970-01-01
    • 2022-06-30
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多