Main concern is that it can happen at the moment of application crash. How is possible to save xml into a file from multiple threads in a safe way?
4 Answers
Save to multiple files. If you are trying to save information for post-mortem purposes, you want to keep things as simple as possible. Concurrently saving to a single XML file is difficult at the best of times; it's the last thing you want to be doing as your program gasps it's last breath.

- 181,030
- 38
- 327
- 365
The same way you normally do. If you have an efficient, quick, and thread-safe method for exporting to XML, you can call it in your master exception handler. You need to take care that you don't do unnecessary work, since you do risk throwing another exception.
If you don't have a thread safe method, you just need to address that as you normally would (thread-safe framework methods, synchronization, etc.)
If the application is critical, there are various precautions you can take (not related to threading), such as keeping a nulled out file of the required size in case you run out of disk space.

- 278,309
- 50
- 514
- 539
I had such a problem writing in log file from multiple thread and what i did was creating a queue to keep data than should be written in file and each write command was calling an add to queue command and also I made the queue thread safe
and there was internal process every time was picking text from queue and append text to file
Here is my code
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());
}
}
}
}
}

- 4,633
- 17
- 22
-
use the class LogManager.Instance.AddtOlog('Hello Log'); – DeveloperX Nov 02 '11 at 06:12
There are transactional NTFS available under Vista and up