【发布时间】:2011-11-11 13:06:58
【问题描述】:
主要问题是它可能发生在应用程序崩溃的时刻。如何以安全的方式将 xml 从多个线程保存到文件中?
【问题讨论】:
主要问题是它可能发生在应用程序崩溃的时刻。如何以安全的方式将 xml 从多个线程保存到文件中?
【问题讨论】:
保存到多个文件。如果您尝试保存信息以供事后分析,您希望使事情尽可能简单。在最好的情况下,同时保存到单个 XML 文件是很困难的;这是你想做的最后一件事,因为你的程序喘不过气来。
【讨论】:
和你平时做的一样。如果您有一个高效、快速且线程安全的方法来导出到 XML,您可以在您的主异常处理程序中调用它。您需要注意不要做不必要的工作,因为您确实有引发另一个异常的风险。
如果您没有线程安全的方法,您只需要像往常一样解决这个问题(线程安全的框架方法、同步等)
如果应用程序很关键,您可以采取各种预防措施(与线程无关),例如保留所需大小的空文件,以防磁盘空间不足。
【讨论】:
我在从多个线程写入日志文件时遇到了这样的问题 我所做的是创建一个队列来保存数据而不是应该写入文件和 每个写命令都在调用添加到队列命令,而且我使队列线程安全
每次从队列中提取文本并将文本附加到文件时都有一个内部进程
这是我的代码
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());
}
}
}
}
}
【讨论】:
在 Vista 及更高版本下有可用的事务性 NTFS
【讨论】: