Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • Home
  • SEARCH
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 8449619
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: June 10, 20262026-06-10T10:45:35+00:00 2026-06-10T10:45:35+00:00

I’m creating a logging class in C# and I need it to be thread

  • 0

I’m creating a logging class in C# and I need it to be thread safe. I’ve implemented TextWriter.Synchronized and locks but I’m getting a very strange issue with the locks where they seem to not work.

I don’t want to use a singleton or a static class because I want to be able to have multiple instances of this logging class at any given time and I want to synchronize the threads based on the log’s filename. So if I have 30 threads with 3 different instances of the Log class all using the same log file, it will synchronize properly and not have any issues. Below is what I’ve come up with so far. I’ve left out some of the code that is irrelevant, like the constructor and close/dispose.

public class Log : IDisposable
{
    public enum LogType
    {
        Information,
        Warning,
        Error
    }

    private FileStream m_File;
    private TextWriter m_Writer;
    private string m_Filename;

    //this is used to hold sync objects per registered log file
    private static SortedList<string, object> s_SyncObjects = new SortedList<string, object>();
    //this is used to lock and modify the above variable
    private static readonly object s_SyncRoot = new object();

    public void WriteLine(Log.LogType MsgType, string Text)
    {
        //this is the problem i think, the lock isn't functioning correctly
        //see below this code for an example log file with issues
        lock (Log.s_SyncObjects[this.m_Filename])
        {
            this.m_Writer.WriteLine(DateTime.Now.ToString("MM/dd/yyyy HH:mm:ss:fffffff") + " " + MsgType.ToString() + ": " + Text);
        }

        return;
    }

    public void Open(string Filename)
    {
        //make filename lowercase to ensure it's always the same
        this.m_Filename = Filename.ToLower();
        this.m_File = new FileStream(Filename, FileMode.Append, FileAccess.Write, FileShare.ReadWrite);
        this.m_Writer = TextWriter.Synchronized(new StreamWriter(this.m_File) { AutoFlush = true });

        //lock the syncroot and modify the collection of sync objects
        //this should make it so that every instance of this class no matter
        //what thread it's running in will have a unique sync object per log file
        lock (Log.s_SyncRoot)
        {
            if (!Log.s_SyncObjects.ContainsKey(this.m_Filename))
                Log.s_SyncObjects.Add(this.m_Filename, new object());
        }
    }
}

To test this I’m creating 3 instances of the logger pointing to the same log file, creating 30 threads and assigning each thread one of the loggers (in order 1,2,3,1,2,3), then I run all 30 threads until I press q.

This works great for writing line by line in a log file and keeping the times the writes happen in the correct order but here is what I get in the log file. It seems that the thread overwrites a portion of the log file and it seems to happen with different instances of the logger on different threads, never the same instance of the logger on different threads. The log file below has the time the entry was created, the logger ID (1 based), the thread ID (0 based) and the message “test”.

08/27/2012 11:47:34:3469116 Information: LOGID: 1, THREADID: 9, MSG: test
08/27/2012 11:47:34:3469116 Information: LOGID: 1, THREADID: 9, MSG: test
08/27/2012 11:47:34:3469116 Information: LOGID: 1, THREADID: 9, MSG: test
08/27/2012 11:47:34:3469116 Information: LOGID: 1, THREADID: 9, MSG: test
08/27/2012 11:47:34:3469116 Information: LOGID: 1, THREADID: 9, MSG: test
08/27/2012 11:47:34:3469116 Information: LOGID: 1, THREADID: 9, MSG: test
08/27/2012 11:47:34:3479116 Information: LOGID: 1, THREADID: 9, MSG: test
08/27/2012 11:47:34:3479116 Information: LOGID: 1, THREADID: 9, MSG: test
08/27/2012 11:47:34:3479116 Information: LOGID: 1, THREADID: 9, MSG: test
08/27/2012 11:47:34:3479116 Information: LOGID08/27/2012 11:47:34:3479116 Information: LOGID: 3, THREADID: 23, MSG: test
08/27/2012 11:47:34:3479116 08/27/2012 11:47:34:3509118 Information: LOGID: 1, THREADID: 0, MSG: test
08/27/2012 11:47:34:3509118 Information: LOGID: 1, THREADID: 0, MSG: test
08/27/2012 11:47:34:3509118 Information: LOGID: 1, THREADID: 0, MSG: test
08/27/2012 11:47:34:3509118 Information: LOGID: 1, THREADID: 0, MSG: test
08/27/2012 11:47:34:3509118 Information: LOGID: 1, THREADID: 0, MSG: test

Notice that 2 of the lines have been mangled. I’m guessing this is due to the locks not working properly, or my misuse of the locks. I would also prefer not to use queuing or any kind of singleton. This behavior doesn’t seem to happen if I change the lock within WriteLine to the m_SyncRoot variable and make it non-static. I have no idea why that works but to me it seems like that is not what I want to do. I also don’t want to lock on a static m_SyncRoot alone because then if I have 3 instances of the logger pointing to 3 different log files then each one will block the other for no reason.

I’m so lost on this, am I completely screwing this up?

In case anyone needs it, here is the test class for generating the threads

public class LogTest
{
    private Log m_Log1;
    private Log m_Log2;
    private Log m_Log3;
    private Thread[] m_Threads;

    private const int THREAD_COUNT = 30;
    private bool m_Done;

    public LogTest()
    {
        this.m_Log1 = new Log();
        this.m_Log2 = new Log();
        this.m_Log3 = new Log();

        this.m_Log1.Open("test.txt");
        this.m_Log2.Open("test.txt");
        this.m_Log3.Open("test.txt");

        this.m_Threads = new Thread[THREAD_COUNT];
        this.m_Done = false;
    }

    public void run()
    {
        for (int i = 0; i < THREAD_COUNT; i++)
        {
            Thread th = new Thread(new ParameterizedThreadStart(this.LogThread));
            this.m_Threads[i] = th;
        }

        for (int i = 0; i < THREAD_COUNT; i++)
        {
            int logId = 1;
            Log temp = this.m_Log1;
            if ((i % 3) == 1)
            {
                temp = this.m_Log2;
                logId = 2;
            }
            else if ((i % 3) == 2)
            {
                temp = this.m_Log3;
                logId = 3;
            }

            this.m_Threads[i].Start(new object[] { logId, i, temp });
        }

        ConsoleKeyInfo key = new ConsoleKeyInfo();
        while ((key = Console.ReadKey()).KeyChar != 'q')
            ;

        this.m_Done = true;
    }

    private void LogThread(object state)
    {
        int loggerId = (int)((object[])state)[0];
        int threadId = (int)((object[])state)[1];
        Log l = (Log)((object[])state)[2];

        while (!this.m_Done)
        {
            l.WriteLine(Log.LogType.Information, String.Format("LOGID: {0}, THREADID: {1}, MSG: {2}", loggerId, threadId, "test"));
        }
    }
}

EDIT: edited to change static m_ to s_ as suggested and added the AutoFlush property to the StreamWriter; setting it to true… still does not work.

  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-06-10T10:45:37+00:00Added an answer on June 10, 2026 at 10:45 am

    I figured out the problem!

    The thread synchronization works as it should and so does the TextWriter.Synchronized() so the problem isn’t really the threads at all. Take this into account:

    I create 3 instances of the Log class and point them all to “test.txt”

    Log log1 = new Log();
    Log log2 = new Log();
    Log log3 = new Log();
    
    log1.Open("test.txt"); //new file handle as instance member
    log2.Open("test.txt"); //new file handle as instance member
    log3.Open("test.txt"); //new file handle as instance member
    

    In each call to Open() I am opening a new file handle to the same file, so I have 3 unique and separate file handles. Each file handle or Stream has it’s own file pointer which seeks along the stream as I read or write.

    So, if we have the following:

    log1.WriteLine("this is some text"); //handled on thread 1
    log2.WriteLine("testing"); //handled on thread 2
    

    If Thread 1 starts to write to the file and completes the file contents will be

    this is some text

    When Thread 2 starts to write, because the file handles and streams are unique the current location of log1’s file pointer is at 16 and log2’s is still at 0 so after log2 is done writing, the resulting log file will read:

    testing some text

    So, all I need to do is make sure I open only 1 unique FileStream per log file and do the synchronization like I have been. Works great now!

    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

I need to clean up various Word 'smart' characters in user input, including but
link Im having trouble converting the html entites into html characters, (&# 8217;) i
I want to count how many characters a certain string has in PHP, but
I have a string like this: La Torre Eiffel paragonata all&#8217;Everest What PHP function
I have a French site that I want to parse, but am running into
In my XML file chapters tag has more chapter tag.i need to display chapters
I am doing a simple coin flipping experiment for class that involves flipping a
I'm parsing an RSS feed that has an &#8217; in it. SimpleXML turns this
Seemingly simple, but I cannot find anything relevant on the web. What is the
I need a function that will clean a strings' special characters. I do NOT

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.