【问题标题】:Why is System.IO.File.AppendAllText locking my file? [duplicate]为什么 System.IO.File.AppendAllText 会锁定我的文件? [复制]
【发布时间】:2018-08-07 23:23:59
【问题描述】:

为什么,这段代码执行后,我不能手动删除生成的文件?我收到此错误消息:

The action can't be completed because the file is open in IIS Express Workers Process.

代码:

System.IO.File.AppendAllText("Filename.txt", "Some Text");

该应用程序是一个 Web 应用程序并在 IIS 中运行。我的理解是AppendAllText自动关闭文件句柄。

我没有使用此代码进行登录。代码的目的是创建一个 CSV 文件,然后将其附加到电子邮件中。如果我执行代码并通过电子邮件发送文件,则永远不会发送文件。如果我然后重新启动 IIS(以释放锁定)并仅执行代码以邮寄文件(不生成),它可以工作。

附加文件的代码...

SmtpClient mailClient = new SmtpClient();
MailMessage msg = new MailMessage();
... Add From, Subject, Body, etc... here
msg.Attachments.Add(new Attachment(filename));
mailClient.Send(msg);

不会引发异常,不会将任何内容写入日志文件以指示问题。电子邮件根本没有发送,如果我转到生成的文件并尝试删除它,我不能因为 IIS 将其锁定。我相信锁定是电子邮件永远不会发送的原因。

【问题讨论】:

  • 你能在你得到文本的地方显示整个代码,附加这个文本并删除这个文件吗?
  • 以防万一您打算使用AppendAllText 实际记录消息 - 不要
  • AppendAllText 只会在写入文件时锁定文件。但是,在 Web 应用程序中,可能会随时写入 很多 个请求。这就是为什么创建日志库不容易的原因。
  • 您是否同时访问该文件?
  • 有很多优秀的日志库可以处理并发日志记录、滚动文件、删除和保留。使用其中之一,例如 Serilog、NLog 或 log4net

标签: c#


【解决方案1】:

File.AppendAllText 写入后关闭文件本身。但是您可能面临这个问题,因为该文件在您的 Web 应用程序中的多个会话之间共享。使用锁防止并发访问。

您应该以不同的方式处理您为 Web 应用程序提供的代码。

using (System.IO.MemoryStream ms = new System.IO.MemoryStream())
{
    System.IO.StreamWriter writer = new System.IO.StreamWriter(ms);
    writer.Write("Some Text");
    writer.Flush();
    writer.Dispose();
    ms.Position = 0;

    System.Net.Mime.ContentType ct = new System.Net.Mime.ContentType(System.Net.Mime.MediaTypeNames.Text.Plain);
    System.Net.Mail.Attachment attach = new System.Net.Mail.Attachment(ms, ct);
    attach.ContentDisposition.FileName = "Filename.txt";

    SmtpClient mailClient = new SmtpClient();
    MailMessage msg = new MailMessage();
    msg.Attachments.Add(attach);
    mailClient.Send(msg);
}

在上面的示例中,附件是在内存中创建的,而不是在文件系统中存储。

【讨论】:

  • 听起来您是在建议 System.IO.File.AppendAllText 不应该用于 Web 应用程序?
  • 不,这种解决方法忽略了根本问题:必须丢弃一次性对象。在这种情况下,SmptClientMailMessage。不仅如此,这种使用StreamWriter 的方法是错误,如果Write() 因任何原因(内存不足?文件太大?)失败,那么您依赖于实现细节:@987654328 @ 没有任何资源(你的 Dispose() 没有被调用)。另一个实现细节:MemoryStream 在被处理后仍然可以使用(默认情况下,StreamWriter.Dispose() 在外部流上执行的操作)。
  • 阿德里亚诺的评论让我指出了正确的方向。重新启动 IIS 后发送电子邮件的事实让我相信问题不在于 SendMail 代码。我错了。显然,创建文件然后通过电子邮件发送它的组合导致发送失败,除非在发出发送命令后处理附件和客户端。感谢所有帮助过的人。 StackOverflow 是一个伟大的平台,因为每个人的努力。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多