c# multithreading and resource locks

Code:
public static void WriteToFileMessageThread(string meterNumber, string message)
        {
            message = Environment.NewLine + DateTime.Now.ToString() + message;

            while (MessageThreadLogLocked)
            {
                Thread.Sleep(15);
            }

            string subdirectory1 = DateTime.Now.Year.ToString() + DateTime.Now.Month.ToString() + DateTime.Now.Day.ToString();
            string path = AppDomain.CurrentDomain.BaseDirectory + "\\Logs\\" + subdirectory1;

            if (!Directory.Exists(path))
            {
                Directory.CreateDirectory(path);
            }

            string subdirectory2 = "MeterLogs";
            string path2 = AppDomain.CurrentDomain.BaseDirectory + "\\Logs\\" + subdirectory1 + "\\" + subdirectory2;

            if (!Directory.Exists(path2))
            {
                Directory.CreateDirectory(path2);
            }

            MessageThreadLogLocked = true;

            string filepath = AppDomain.CurrentDomain.BaseDirectory + "\\Logs\\" + subdirectory1 + "\\" + subdirectory2 + "\\" + meterNumber + ".txt";
            if (!File.Exists(filepath))
            {
                using (StreamWriter sw = File.CreateText(filepath))
                {
                    sw.WriteLine(message);
                }
            }
            else
            {
                using (StreamWriter sw = File.AppendText(filepath))
                {
                    sw.WriteLine(message);
                }
            }

            Thread.Sleep(10);

            MessageThreadLogLocked = false;
        }

If you do go the async route, you can do something like this in .Net Framework (not tested as I have to shoot):

C#:
public static async Task WriteToFileMessageThreadAsync(string meterNumber, string message)
{
    var data = string.Concat(Environment.NewLine, DateTime.Now.ToString(), message);
   
    var path = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Logs", DateTime.Now.ToString("yyyyMMdd"), "MeterLogs");

    if (Directory.Exists(path) == false)
    {
        Directory.CreateDirectory(path);
    }

    var filename = Path.Combine(path, $"{meterNumber}.txt");

    using (var sw = new StreamWriter(filename, true))
    {
        await sw.WriteAsync(data);
        await sw.FlushAsync();
    }
}

Try to reduce the string manipulation. There would be a lot of strings allocated on the Heap and consuming memory, meaning that the GC has to work harder to clean up. When the GC is running, code is not.

You also don't need to check if the File.Exists and then Append or Create because .Net will do that for you.
 
You can always take a look at the IL generated code for your code when using "Await".

It generates a lot of code that uses a state machine to bring the processing back into the function after the awaited Task is completed. It DOES NOT sit there blocking processing. It releases the thread back to the ThreadPool for something else (if needed/waiting) to use the/a thread. When that awaited Task finishes, it will get a thread (which might or might not be the same thread) from the ThreadPool and then continue processing code after it. This is why Async/Await is awesome for scalability and performance. .Net does a lot behind the scenes.

Here are some really good tips from the Microsoft Devs:
: https://github.com/davidfowl/AspNetCoreDiagnosticScenarios/blob/master/AsyncGuidance.md
David is "Partner Software Architect at Microsoft on the ASP.NET team, Creator of SignalR". He knows his ****.

Those tips aren't only for .Net Core. A lot is available in .Net Framework as well.
and this is extremely important for cloud computing/VM's, where often you are using a vCPU with 1 or 2 threads (but CPU threads !=OS threads, but there is still a physical limit on how many OS threads can be created/used effectively)
 
Top
Sign up to the MyBroadband newsletter
X