【问题标题】:safe way to save xml file when call can be from a multiple threads当调用可以来自多个线程时,保存 xml 文件的安全方法
【发布时间】:2011-11-11 13:06:58
【问题描述】:

主要问题是它可能发生在应用程序崩溃的时刻。如何以安全的方式将 xml 从多个线程保存到文件中?

【问题讨论】:

    标签: c# .net


    【解决方案1】:

    保存到多个文件。如果您尝试保存信息以供事后分析,您希望使事情尽可能简单。在最好的情况下,同时保存到单个 XML 文件是很困难的;这是你想做的最后一件事,因为你的程序喘不过气来。

    【讨论】:

      【解决方案2】:

      和你平时做的一样。如果您有一个高效、快速且线程安全的方法来导出到 XML,您可以在您的主异常处理程序中调用它。您需要注意不要做不必要的工作,因为您确实有引发另一个异常的风险。

      如果您没有线程安全的方法,您只需要像往常一样解决这个问题(线程安全的框架方法、同步等)

      如果应用程序很关键,您可以采取各种预防措施(与线程无关),例如保留所需大小的空文件,以防磁盘空间不足。

      【讨论】:

        【解决方案3】:

        我在从多个线程写入日志文件时遇到了这样的问题 我所做的是创建一个队列来保存数据而不是应该写入文件和 每个写命令都在调用添加到队列命令,而且我使队列线程安全

        每次从队列中提取文本并将文本附加到文件时都有一个内部进程

        这是我的代码

        using System;
        using System.Collections.Generic;
        using System.Linq;
        using System.Text;
        
        namespace AC.ChatServer.Classes
        {
            public delegate void OnDataAddedHandler(string data);
            public class LogManager
            {
                #region Fields
                private System.Threading.Mutex logMutex;
                private string filePath;
                private static LogManager instance;
                private AndcQ q;
                #endregion
        
        
                #region Property
                public void Initiate()
                {
                }
                public static LogManager Instance
                {
                    get
                    {
                        if (instance == null)
                            instance = new LogManager();
                        return instance;
                    }
                }
                #endregion
        
                #region Helper function
                public void AddtOlog(string data)
                {
                    q.Enqueue(data);
                }
                #endregion
        
                #region Constructor
                private LogManager()
                {
        
                    q = new AndcQ(100);
                    filePath = System.Configuration.ConfigurationManager.AppSettings["LogFileFolder"];
                    logMutex = new System.Threading.Mutex();
                    q.DataAdded += new OnDataAddedHandler(q_DataAdded);
        
                }
                private string GetFileName()
                {
                    string fileName = DateTime.Today.ToString("_yyyyMMdd");
                    return string.Format(@"{0}\{1}.txt", filePath, fileName);
                }
                private void WriteToFile(object data)
                {
        
                    string fileName = GetFileName();
                    using (System.IO.StreamWriter sw = new System.IO.StreamWriter(fileName, true, Encoding.UTF8))
                    {
                        sw.WriteLine(data.ToString());
                    }
                }
                private delegate void WriteToFileCallBack(string data);
                void q_DataAdded(string data)
                {
                    logMutex.WaitOne();
                    WriteToFileCallBack caller = new WriteToFileCallBack(WriteToFile);
                    IAsyncResult r = caller.BeginInvoke(data, null, null);
                    caller.EndInvoke(r);
                    logMutex.ReleaseMutex();
                }
                #endregion
            }
            public class AndcQ : System.Collections.Queue
            {
                #region Events
                public event OnDataAddedHandler DataAdded;
                #endregion
        
        
                public AndcQ(int capacity)
                    : base(capacity)
                {
        
                }
                public AndcQ()
                    : base()
                {
        
                }
                public new void Enqueue(object obj)
                {
        
                    base.Enqueue(obj);
                    if (DataAdded != null)
                        lock (this)
                        {
                            if (this.Count > 0)
                            {
                                DataAdded(this.Dequeue().ToString());
                            }
                        }
                }
            }
        }
        

        【讨论】:

        • 使用类 LogManager.Instance.AddtOlog('Hello Log');
        【解决方案4】:

        在 Vista 及更高版本下有可用的事务性 NTFS

        Atomic file copy under .NET

        Atomicity of File.Move

        Atomic file copy VB.Net

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2017-07-15
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多