I`m sorry about the title.
So, when i start my program i start to write everything in log.txt. The problem is when i start second instance of same program and they work at same time. Second program crash because log file is in use in this time ( by first program ) how to make able second program to also to write in that file ?
Or create new file ?

Recommended Answers

All 9 Replies

I would create a log file for both programs, im not aware of a way to write simultaneously to log files. Perhaps one of the more experienced members of the forum does?

They are not different programs. It is one program just runned 2 times.

Fine, I would create a uniquely identified log for each instance of the program.

However have found this which might provide some insight into how to do it, look at the selected answer on it.

I tried this but i can`t do it. I use this to log for program now. Is there any way to put on this some condition if the file is use to create new ?

if (!File.Exists("\\log.txt")) 
 {
    log = new StreamWriter("\\log.txt");
 }                
 else
    {
       log = File.AppendText("\\log.txt");
    }    
 log.WriteLine(DateTime.Now);

Method which checks if it can open the file to write and if it can signals that the file is not in use. Else catches the exception caused and flags file as in use.

public bool CheckFileInUse(string File)
{
    bool success = false;
    try
    {
        FileStream fileStream;
        using (fileStream = new FileStream(File, FileMode.Open, FileAccess.Write)
        {

        }
        fileStream.Close()
        success = false;
    }
    catch (IOException exn)
    {
        if(ex.Message.ToString().Contains("The process cannot access the file")
        {
            success = true;
        }
    }
    //True = in use, False = not in use
    return success;
}

and if is in use how to create new lets say log1.txt

Hmmm, well you couldnt use a variable inside the app to store which number it is adding to the file as each instance of the application would have it own version of this variable.

Could check the file name of the log files found, get the highest number (if there is one) and then increment that by one to get the new name.

So for example if log1 exists it would make log2.

Easily done with a bit of RegEx :)

Personally, if I were you I'd have each app write to a log file of its own regardless of whether the first is in use, as it would seem cleaner. But thats my opinion.

any example will be appreciate how when i run program to check if file log.txt is in use to create log1.txt. I`m not so experienced still learning

If you want them to write to the same log file you will have to syncronize the two applications such that neither of them try to access the same resources simultaneosly. An easy class for cross-process syncronization is the System.Threading.Mutex class.

Note you will have to use a named mutex, unnamed ones are considered local and not operating system wide. i would also try to use a unique name for the mutex to avoid any conflicts with existing system mutexes. Here's a quick, extremely thread/process safe class for writing to a file asyncronously demonstrating the power of mutexes, queues, and some other thread stuff. This stuff can be a bit overwhelming to a new programmer but feel free to use this class freely and ask any questions you might have.

using System.Collections;
using System.IO;
using System.Threading;
//Thread safe async file writer with inter-process file locking via mutex
class SyncronizedFileWriter
{
    //Private syncronizing object to ensure thread safety of the class
    object SyncRoot = new object();
    //Queue to hold data to write
    Queue DataToWrite = new Queue();
    //Thread to write the queue to the file in
    Thread DequeThread;
    string Filepath = "mylogfile.log";
    //CTOR
    public SyncronizedFileWriter(string filepath)
    {
        Filepath = filepath;
    }
    //Adds an item to a logfile (complexity is totally transparent to caller)
    public void Write(string data)
    {
        //Lock a private reference to make this class (and its queue) threadsafe
        lock (SyncRoot)
        {
            var syncQue = Queue.Synchronized(DataToWrite);
            syncQue.Enqueue(data);

            if (DequeThread == null || !DequeThread.IsAlive)
            {
                DequeThread = new Thread(() => DequeData());
                DequeThread.Start();
            }
        }
    }
    //Iterates the queue of data and writes it to a syncronized file
    private void DequeData()
    {
        var syncQue = Queue.Synchronized(DataToWrite);
        while (syncQue.Count != 0)
        {
            WriteSyncronized(syncQue.Dequeue().ToString(), Filepath);
        }
    }
    //writes data to a file
    private void WriteData(string data, string file)
    {
        using (var stream = new System.IO.StreamWriter(file, true))
        {
            stream.Write(data);
        }
    }
    //Calls writedata, but uses a mutex lock to ensure exclusive access to the resource
    private void WriteSyncronized(string data, string file)
    {
        //I generated a GUID for my mutex name to make sure it doesnt conflict with any other mutex on the system
        using (var mutex = new System.Threading.Mutex(false, "12503E3D-9834-4B0E-A83D-A2AE9ECD29EA"))
        {
            mutex.WaitOne();
            WriteData(data, file);
            mutex.ReleaseMutex();
        }
    }
}
Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.