You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

StreamWriter报错文件被其他进程占用,疑因读写及开关频率过高

解决StreamWriter高频调用时“文件被其他进程占用”的问题

嘿,这个坑我之前踩过!当你高频调用writeLog方法写日志时,确实会因为文件打开/关闭的速度跟不上调用频率,导致前一次的文件流还没完全释放,下一次就尝试打开同一个文件,触发“文件被其他进程占用”的错误。

问题根源

你原来的代码每次调用writeLog都会新建一个StreamWriter实例,哪怕用了using语句确保释放,短时间内多次调用时,操作系统的文件系统可能还没完成文件的解锁操作,下一次打开请求就来了,直接造成冲突。

最优解决方案:复用StreamWriter实例

我们可以把StreamWriter做成静态实例,保持文件打开状态直到程序退出再关闭,这样既避免了频繁打开/关闭文件的开销,也从根本上解决了占用冲突问题。同时要加上线程锁,确保多线程调用时的安全性。

修改后的代码示例:

private static StreamWriter _logWriter;
private static readonly object _logLock = new object();

public static void writeLog(string msg)
{
    lock (_logLock)
    {
        if (_logWriter == null)
        {
            // 构建日志目录和文件路径
            string currentMonth = DateTime.Now.ToString("MMM");
            string currentYear = DateTime.Now.ToString("yyyy");
            string directoryName = Path.Combine(@"C:\AutoSkill\LogFiles", $"{currentMonth}-{currentYear}");
            
            // 直接创建目录,已存在的话不会报错
            Directory.CreateDirectory(directoryName);
            
            string logFileName = $"Log_{DateTime.Now:yyyyMMdd}.txt";
            string logFilePath = Path.Combine(directoryName, logFileName);
            
            // 以追加模式打开文件,设置自动刷新缓冲区
            _logWriter = new StreamWriter(logFilePath, true, Encoding.UTF8)
            {
                AutoFlush = true
            };
        }

        // 写入带时间戳的日志内容
        _logWriter.WriteLine($"{DateTime.Now:yyyy-MM-dd HH:mm:ss} - {msg}");
    }
}

// 记得在程序退出时释放资源(比如控制台Main末尾、WinForm的FormClosing事件)
public static void CloseLogWriter()
{
    lock (_logLock)
    {
        _logWriter?.Flush();
        _logWriter?.Close();
        _logWriter?.Dispose();
        _logWriter = null;
    }
}

关键细节说明

  • 静态实例+锁:静态实例保证整个应用生命周期内只打开一次文件,线程锁避免多线程同时写入导致的异常或日志乱序。
  • AutoFlush = true:确保日志内容立即写入文件,而不是留在缓冲区,避免程序意外退出时丢失日志。
  • Directory.CreateDirectory:不用提前判断目录是否存在,这个方法会自动处理已存在的情况,简化代码逻辑。

备选方案(不推荐高频场景)

如果实在不想复用实例,也可以用File.AppendAllText,但它本质还是每次调用都打开/关闭文件,高频调用下依然可能出现占用问题,代码示例:

private static readonly object _logLock = new object();

public static void writeLog(string msg)
{
    string currentMonth = DateTime.Now.ToString("MMM");
    string currentYear = DateTime.Now.ToString("yyyy");
    string directoryName = Path.Combine(@"C:\AutoSkill\LogFiles", $"{currentMonth}-{currentYear}");
    Directory.CreateDirectory(directoryName);
    
    string logFilePath = Path.Combine(directoryName, $"Log_{DateTime.Now:yyyyMMdd}.txt");
    string logContent = $"{DateTime.Now:yyyy-MM-dd HH:mm:ss} - {msg}{Environment.NewLine}";
    
    // 加锁避免多线程写入冲突
    lock (_logLock)
    {
        File.AppendAllText(logFilePath, logContent, Encoding.UTF8);
    }
}

这个方案在低频率调用时没问题,但高频场景下还是推荐复用StreamWriter的方式,性能和稳定性都更优。

内容的提问来源于stack exchange,提问作者Ben R

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.22 08:08:32