【问题标题】:c#: best way to ensure my file closedc#:确保我的文件关闭的最佳方法
【发布时间】:2018-08-30 11:29:01
【问题描述】:

所以我有这个function 来检查我的File 是否仍在使用(以便在尝试复制和删除之前等待):

    private static bool IsFileLocked(FileInfo file)
    {
        FileStream stream = null;

        try
        {
            using (stream = file.Open(FileMode.Open, FileAccess.ReadWrite, FileShare.None))
            {

            }
        }
        catch (IOException)
        {
            // The file is unavailable because it is:
            // 1. Still being written to.
            // 2. Being processed by another thread.
            // 3. Does not exist (has already been processed).

            if (stream != null)
                stream.Close();
            return true;
        }
        finally
        {
            if (stream != null)
                stream.Close();
        }

        //file is not locked
        return false;
    }

所以这足以调用Close() 方法或者使用using 来确保file 在完成我的方法后关闭?

【问题讨论】:

  • 是的,包装在 using 块中是个好主意:msdn
  • 将 try-catch 包装到 ?
  • 只有try块里面的代码,当抛出一些异常时会自动调用dispose,所以如果需要,文件会被关闭。
  • 所有这些代码实际上都是无用的。它可以在创建 Stream 的那一刻“免费使用”,并在 Stream 释放它的那一刻锁定它
  • 尝试真正的操作,如果失败则知道它已被锁定。您可能希望以指数级等待时间重试几次

标签: c# file stream


【解决方案1】:

其他答案和 cmets 已经指出了您的代码中的冗余以及为什么您当前的方法可能效果不佳。我将尝试为您提供一些关于如何解决更普遍问题的指导。

我使用的方法如下:

  1. 创建一个并发队列来跟踪文件挂起的副本。根据需要方便地更新此队列添加文件;一旦任何先前的文件处理以未知的未来完成开始(*))。
  2. 创建一个并发队列来跟踪待删除的文件。
  3. 在工作线程上设置计时器并定期迭代符合复制条件的文件并尝试复制每个文件。成功删除文件并将它们排入待删除队列。
  4. 在同一个工作线程(或具有自己计时器的不同工作线程)上迭代所有待删除的文件并尝试删除每个文件。成功删除文件。
  5. 继续前进,直到两个队列都为空或世界末日。

故事的寓意:检查文件是否被锁定以对其执行某些阻止操作是没有意义的,在您执行检查后没有任何东西可以阻止任何东西锁定它。这样做的方法是简单地尝试对文件执行您需要执行的操作,如果它不起作用,请稍后再试。如果是这样,嘿,工作完成了,太好了。

(*) 如果你确实知道文件处理何时完成,那么这一切都是没有意义的,当上一步完成时复制并删除。

【讨论】:

    【解决方案2】:

    我认为您错过了 using 语句的要点。具有 IDisposible 的类可以与 using 语句一起使用。当 using 语句完成时,“used”类会自动释放。正确编写的类将关闭所有打开的操作并处置该类。因此,简而言之,只需执行以下操作。使用 FileAccess 和 FileShare 来满足您的需求。

    void t()
        {
            using (FileStream _fileStream = new FileStream(_fileName, FileMode.Open, FileAccess.Read, FileShare.Read))
            {
                using (StreamReader sr = new StreamReader(_fileStream))
                {
                   // do file operations
                }
            }
        }
    

    【讨论】:

    • 我只想检查文件是否仍在处理中并返回真或假,如果这是真或假,我需要在哪里返回? (我通过 while 调用这个函数,直到它返回 false)
    • 您是否在控制文件的原始操作?如果你是,那你应该有你的 using 语句。在这种情况下,您不需要测试文件是否打开,因为它在您的 using 语句期间是打开的。也许,我误解了你的代码是如何工作的。原始文件操作是否来自另一个线程的异步操作?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-05-21
    • 2015-03-16
    • 2013-04-01
    • 1970-01-01
    相关资源
    最近更新 更多