private static void Main() { SetupLoggers(); // print our first message. It will go to cout because that is the default. LogP.WriteLine(LogLevel.Info, "This is an informational message."); var variable = 8; // Here is a debug message. It won't print though because its log level is too low (it is below LINFO). LogP.WriteLine(LogLevel.Debug, $"The integer variable is set to {variable}"); if (variable > 4) { LogP.WriteLine(LogLevel.Warn, $"The variable is bigger than 4! Its value is {variable}"); } LogP.WriteLine(LogLevel.Info, "make two threads"); var action = new Dlib.ThreadAction(Thread); Dlib.CreateNewThread(action, new IntPtr(0)); Dlib.CreateNewThread(action, new IntPtr(0)); var myTest = new Test(); myTest.Warning(); LogP.WriteLine(LogLevel.Info, "we are going to sleep for half a second."); // sleep for half a second Dlib.Sleep(500); LogP.WriteLine(LogLevel.Info, "we just woke up"); LogP.WriteLine(LogLevel.Info, "program ending"); // It is also worth pointing out that the logger messages are atomic. This means, for example, that // in the above log statements that involve a string literal and a variable, no other thread can // come in and print a log message in-between the literal string and the variable. This is good // because it means your messages don't get corrupted. However, this also means that you shouldn't // make any function calls inside a logging statement if those calls might try to log a message // themselves since the atomic nature of the logger would cause your application to deadlock. }