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

如何处理被两个并行库共享、需持续读写的Log.txt文件?

解决多进程共享日志文件的写入与清理冲突问题

核心问题分析

原代码中Parent进程创建FileStream时未指定共享权限,默认会独占文件;Child进程使用File.WriteAllText也会独占文件访问,导致双方互相阻塞抛出文件占用错误。以下是两种可行的解决方案:


方案一:修改文件流共享权限,实现实时读写+清空

Parent进程(持续写入)

将原有的每次写入后关闭流改为持续打开流,并指定FileShare.ReadWrite允许Child进程同时访问:

// 全局持有流对象,避免频繁打开关闭
private static FileStream _logFileStream;
private static StreamWriter _logWriter;

// 初始化日志写入器(程序启动时调用一次)
public static void InitializeLogWriter(string logFilePath)
{
    // 关键:指定FileShare.ReadWrite,允许其他进程读写该文件
    _logFileStream = new FileStream(
        logFilePath, 
        FileMode.Append, 
        FileAccess.Write, 
        FileShare.ReadWrite);
    _logWriter = new StreamWriter(_logFileStream) { AutoFlush = true }; // 自动刷新避免缓存
}

// 写入日志的方法
public static void WriteLogEntry(string strLog)
{
    _logWriter.WriteLine(strLog);
}

// 程序退出时释放资源
public static void ShutdownLogWriter()
{
    _logWriter?.Dispose();
    _logFileStream?.Dispose();
}

Child进程(清理文件)

放弃File.WriteAllText(独占文件),改用FileStream配合SetLength(0)实现安全清空,同时匹配共享权限:

public static void ClearLogFile(string logFilePath)
{
    using (var fileStream = new FileStream(
        logFilePath, 
        FileMode.Open, 
        FileAccess.Write, 
        FileShare.ReadWrite))
    {
        // 截断文件至0长度,实现清空
        fileStream.SetLength(0);
        fileStream.Flush(); // 立即写入磁盘
    }
}

方案二:日志轮转机制(更稳定的生产级方案)

如果需要保留历史日志且避免频繁清空的冲突,可采用日志轮转:Child将当前日志文件重命名归档,Parent自动切换到新文件继续写入。

Parent进程(支持自动切换日志文件)

private static string _baseLogPath;
private static FileStream _logFileStream;
private static StreamWriter _logWriter;

public static void InitializeLogWriter(string baseLogPath)
{
    _baseLogPath = baseLogPath;
    OpenActiveLogFile();
}

private static void OpenActiveLogFile()
{
    _logFileStream = new FileStream(
        _baseLogPath, 
        FileMode.Append, 
        FileAccess.Write, 
        FileShare.ReadWrite);
    _logWriter = new StreamWriter(_logFileStream) { AutoFlush = true };
}

public static void WriteLogEntry(string strLog)
{
    // 检查当前日志文件是否被重命名(Child操作),如果不存在则重新创建
    if (!File.Exists(_baseLogPath))
    {
        _logWriter.Dispose();
        _logFileStream.Dispose();
        OpenActiveLogFile();
    }
    _logWriter.WriteLine(strLog);
}

public static void ShutdownLogWriter()
{
    _logWriter?.Dispose();
    _logFileStream?.Dispose();
}

Child进程(归档日志)

public static void ArchiveAndResetLog(string baseLogPath)
{
    if (!File.Exists(baseLogPath)) return;
    
    // 生成带时间戳的归档文件名
    string archivePath = $"{Path.GetFileNameWithoutExtension(baseLogPath)}_{DateTime.Now:yyyyMMddHHmmss}{Path.GetExtension(baseLogPath)}";
    
    // 重命名当前日志文件(因Parent设置了FileShare.ReadWrite,可正常执行)
    File.Move(baseLogPath, archivePath);
    // 此时Parent会自动创建新的日志文件继续写入
}

额外说明

如果需求是删除重复数据而非清空整个文件,可在Child进程中按以下步骤操作:

  1. 以FileShare.ReadWrite权限打开文件读取所有内容
  2. 过滤掉重复的日志条目
  3. 重新打开文件(或复用现有流),调用SetLength(0)清空后写入过滤后的内容

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.22 20:51:13