在专门打开的文件中附加文本

时间:2014-05-16 12:36:12

标签: c# multithreading file-management file-locking

我正在尝试实现锁定场景,其中多个线程同时或在不同时间访问同一文件。在测试时,代码似乎覆盖现有的行而不是追加新的行。

namespace SMPPService
{
public static class LogFile
{
    public static void WriteErrorLog(Exception ex)
    {
        byte[] buf = GetBytes(DateTime.Now.ToString() + ": " + ex.Source.ToString().Trim() + "; " + ex.Message.ToString().Trim());

        Lock(HttpRuntime.AppDomainAppPath + "\\Exceptions.txt",
                (f) =>
                {
                    try
                    {
                        f.Write(buf, 0, buf.Length);
                    }
                    catch (IOException ioe)
                    {
                        // handle IOException
                    }
                }, buf);
    }

    public static void WriteErrorLog(string Message)
    {
        byte[] buf = GetBytes(DateTime.Now.ToString() + ": " + Message);           

        Lock(HttpRuntime.AppDomainAppPath + "\\LogFile.txt",
                (f) =>
                {
                    try
                    {
                        f.Write(buf, 0, buf.Length);
                    }
                    catch (IOException ioe)
                    {
                        // handle IOException
                    }
                }, buf);

        System.Threading.Thread.Sleep(60000);

    }

    public static void Lock(string path, Action<FileStream> action,byte [] lines)
    {
        var autoResetEvent = new AutoResetEvent(false);

        while (true)
        {
            try
            {
                using (var file = File.Open(path,
                                            FileMode.OpenOrCreate,
                                            FileAccess.ReadWrite,
                                            FileShare.Write))
                {
                    action(file);                              
                    break;
                }
            }
            catch (IOException)
            {
                var fileSystemWatcher =
                    new FileSystemWatcher(Path.GetDirectoryName(path))
                    {
                        EnableRaisingEvents = true
                    };

                fileSystemWatcher.Changed +=
                    (o, e) =>
                    {
                        if (Path.GetFullPath(e.FullPath) == Path.GetFullPath(path))
                        {
                            autoResetEvent.Set();
                        }
                    };

                autoResetEvent.WaitOne();
            }
        }
    }
    static byte[] GetBytes(string str)
    {
        byte[] bytes = new byte[str.Length * sizeof(char)];
        System.Buffer.BlockCopy(str.ToCharArray(), 0, bytes, 0, bytes.Length);
        return bytes;
    }
 }
 }

用法

LogFile.WriteErrorLog("Requesting SMPP Client from WMAS..." + " " + "Date:" + DateTime.Now + " " + "Source Address:" + msisdn);

2 个答案:

答案 0 :(得分:0)

FileShare.Write

来自MSDN

  

允许随后打开文件进行书写。

这正是您不想使用的旗帜。对于文件,最简单的锁定方法是让文件系统为您执行此操作,使用FileShare.Read(以便有人可以查看日志),如果打开失败则重试共享违规。

实现你自己的锁定只会在文件系统已经存在的情况下重新创建,但很糟糕。

此外,而不是自己处理编码(使边缘情况正确并不容易):

  • 以具有指定编码的文本文件打开(UTF-8将是我的选择)。
  • 打开追加的文件,这样就会在最后写入新内容。

StreanWriter的构造函数有一个超载来执行此操作。

编辑:快速检查reference source:这确实使用FileShare.Read

答案 1 :(得分:0)

您应该使用File.AppendAllLines代替您的lock方法。 File.AppendAllLines 线程安全,您必须将其锁定。

private object lockObject = new object();
private string fileName = Path.Combine(HttpRuntime.AppDomainAppPath, "LogFile.txt");

public static void WriteErrorLog(string Message)
{       
    lock(lockObject)
    {
        File.AppendAllLines(fileName, new string[] { Message + "\n" });
    }
}

请注意{。3}}是在.Net 4中引入的,你必须在旧框架中使用File.AppendAllLines