【问题标题】:Delete file after creation创建后删除文件
【发布时间】:2012-01-29 06:49:34
【问题描述】:

我试图在创建文件后删除它,但根本无法删除。 错误消息是它仍在被进程使用。 我正在开发一个 winform 应用程序。

这是我的代码:

XmlDocument xmlDoc = new XmlDocument();
XmlDeclaration xmlDec = xmlDoc.CreateXmlDeclaration("1.0", "utf-8", null);
xmlDoc.AppendChild(xmlDec);

XmlElement elmRoot = xmlDoc.CreateElement("testConfig");
xmlDoc.AppendChild(elmRoot);

GetConfigTags(xmlDoc, elmRoot, clientToken);

StreamWriter wText = 
    new StreamWriter(CommonCodeClass.configLocation + "EmailConfig.xml");
xmlDoc.Save(wText);
wText.Flush();
wText.Close();
wText.Dispose();
File.Delete(CommonCodeClass.configLocation + "EmailConfig.xml");

我也试过下面的代码,但同样的错误,文件被另一个进程使用

try
{
    File.Delete(CommonCodeClass.configLocation + "EmailConfig.xml");
}
catch  //or maybe in finally
{
    GC.Collect(); //kill object that keep the file. I think dispose will do the trick as well.
    Thread.Sleep(500); //Wait for object to be killed. 
    File.Delete(CommonCodeClass.configLocation + "EmailConfig.xml"); //File can be now deleted
    log.Error(CommonCodeClass.configLocation + "EmailConfig.xml" + " was deleted forcefully as it was being used by the process.");

}

我是否在任何地方都错过了关闭文件?

请帮忙。谢谢。

这里是 getconfigtag 的代码:它只是创建一个要在配置文件中应用的标签。

 internal static void GetConfigTags(XmlDocument xmlDoc, XmlElement elmRoot, string clientToken)
    {
        // Username Element            
        XmlElement elmUsername = xmlDoc.CreateElement(CommonCodeClass.xml_Username);
        XmlAttribute xaUsername = xmlDoc.CreateAttribute("val");
        xaUsername.Value = "singleVal";
        elmUsername.InnerXml = "";
        elmUsername.Attributes.Append(xaUsername);
        elmRoot.AppendChild(elmUsername);
     }

堆栈跟踪:

在 System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath) 在 System.IO.File.Delete(字符串路径) 在 C:\Users\ddsds\Documents\Visual Studio 2008\Projects\ShareMgmt\Mgmt\CommonCodeClass.cs 中的 ShareMgmt.CommonCodeClass.EmailTheConfigFile(字符串 userEmail,字符串 clientToken):第 756 行 在 C:\Users\ddsds\Documents\Visual Studio 2008\Projects\ShareMgmt\Mgmt\UsersForm.cs:line 1122 中的 ShareMgmt.UsersForm.btnConfigToAdmin_Click(Object sender, EventArgs e)

【问题讨论】:

  • GetConfigTags 方法有什么作用?此外,您应该养成使用块进行编码的习惯。这样您就不必担心编写 Dispose 调用。
  • 您确定错误来自 File.Delete 行吗?它可能来自“new StreamWriter(...)”行吗?
  • 代码似乎对我有用。请包括堆栈跟踪。此外,GC 收集不会删除文件锁定。
  • 作为一般规则,将 IDisposable 对象 (wText) 包装在 using 语句中。然后对Flush()Close()Dispose() 的调用都可以消失了。
  • 从您的堆栈跟踪来看,您似乎正在尝试通过电子邮件发送 XML 文件。您在使用 MailMessage.Attachments.Add(...) 吗?我想知道这是否保留了参考。

标签: c# asp.net winforms file


【解决方案1】:

“我是否在任何地方丢失了关闭文件?”您可以确定使用“使用”语句关闭文件。

    XmlDocument xmlDoc = new XmlDocument();
    XmlDeclaration xmlDec = xmlDoc.CreateXmlDeclaration("1.0", "utf-8", null);
    xmlDoc.AppendChild(xmlDec);

    XmlElement elmRoot = xmlDoc.CreateElement("testConfig");
    xmlDoc.AppendChild(elmRoot);

    GetConfigTags(xmlDoc, elmRoot, clientToken);

    using (StreamWriter wText = new StreamWriter(CommonCodeClass.configLocation + "EmailConfig.xml"))
    {
            xmlDoc.Save(wText);
            wText.Flush();
    }

    File.Delete(CommonCodeClass.configLocation + "EmailConfig.xml");

此代码适用于我,但您的原始代码的变体也适用,因此除此之外,我不太确定问题出在哪里。

附录:

您的堆栈跟踪显示您正在尝试通过电子邮件发送 XML 文件。如果是这种情况,并且您正在使用 SmtpClient,您甚至不需要将 XML 文档写入文件。

MemoryStream memoryStream = new MemoryStream();
xmlDoc.Save(memoryStream);

// ...

mailMessage.Attachments.Add(
    new Attachment(memoryStream, "EmailConfig.xml", "application/xml"));

【讨论】:

    【解决方案2】:

    该代码适用于我,但我建议每次使用实现 IDisposable 的类的实例时都使用 using 语句。

    另一件事:永远不要调用GC.Collect() 来尝试强制GC 为您进行清理。如果您正确处理您的实例(使用 using 关键字您不会忘记),那么 GC 不需要您告诉他该做什么。

    【讨论】:

      【解决方案3】:

      xmlDoc 仍然有文件的句柄。

      将创建文件的代码放在一个函数中,这样当您去删除时,xmlDoc 就会超出范围。您可能必须调用 GC.Collect()。可以肯定的是,这也是我遇到的最大问题之一。

      或者您可以将{} 放在代码周围而不将其放入函数中。您可以随时使用{} 来制作不同的作用域。

      所以你上面的代码变成了:

      // other preceeding code    
      {
          XmlDocument xmlDoc = new XmlDocument();
          XmlDeclaration xmlDec = xmlDoc.CreateXmlDeclaration("1.0", "utf-8", null);
          xmlDoc.AppendChild(xmlDec);
      
          XmlElement elmRoot = xmlDoc.CreateElement("testConfig");
          xmlDoc.AppendChild(elmRoot);
      
          GetConfigTags(xmlDoc, elmRoot, clientToken);
      
          StreamWriter wText = 
              new StreamWriter(CommonCodeClass.configLocation + "EmailConfig.xml");
          xmlDoc.Save(wText);
          wText.Flush();
          wText.Close();
          wText.Dispose();
      }
      
      File.Delete(CommonCodeClass.configLocation + "EmailConfig.xml");
      

      【讨论】:

      • 不要依赖变量的范围来判断一个实例是否被GCed。我们无法判断 GC 何时完成这项工作。
      • 就像我提到的 - 这整个文件锁定情况是一个问题,但从应用程序的角度来看,范围应该删除锁定。
      • 不。退出范围实际上什么都不做。到达范围结束后,GC 不会立即执行此工作。
      猜你喜欢
      • 2016-05-31
      • 1970-01-01
      • 2012-08-05
      • 2015-06-23
      • 1970-01-01
      • 2016-09-02
      • 1970-01-01
      • 1970-01-01
      • 2013-06-10
      相关资源
      最近更新 更多