{"id":529,"date":"2003-10-26T17:31:03","date_gmt":"2003-10-26T21:31:03","guid":{"rendered":"http:\/\/wordpress.cephas.net\/?p=529"},"modified":"2007-10-11T19:46:58","modified_gmt":"2007-10-12T03:46:58","slug":"logging-in-c-enumerations-thread-safe-streamwriter","status":"publish","type":"post","link":"https:\/\/cephas.net\/blog\/2003\/10\/26\/logging-in-c-enumerations-thread-safe-streamwriter\/","title":{"rendered":"Logging in C#: enumerations, thread-safe StreamWriter"},"content":{"rendered":"<p><a href=\"http:\/\/www.joecheng.com\/\">Joe<\/a> gave me some <a href=\"http:\/\/cephas.net\/MT-2.21\/mt-comments.cgi?entry_id=491\">great feedback<\/a> on the <a href=\"http:\/\/cephas.net\/blog\/2003\/08\/22\/logging_in_c.html\">C# logging utility<\/a> I wrote about a couple months ago. Per his suggestions, I modified it in the following ways:<\/p>\n<p>1) Instead of using public static int variables as levels, I added an enumeration:<br \/>\n<code><br \/>\nenum Priority : int {<br \/>\n&nbsp;&nbsp;OFF = 200,<br \/>\n&nbsp;&nbsp;DEBUG = 100,<br \/>\n&nbsp;&nbsp;INFO = 75,<br \/>\n&nbsp;&nbsp;WARN = 50,<br \/>\n&nbsp;&nbsp;ERROR = 25,<br \/>\n&nbsp;&nbsp;FATAL = 0<br \/>\n}<br \/>\n<\/code><br \/>\nAn enumeration is a value type (ie: the enumeration is not a full fledged object) and thus is allocated on the stack.  I&#8217;m guessing that Joe suggested the use of an enumeration for 2 reasons. First, an enumeration groups the constants together&#8230; in some sense it encapsulates what was a group of unrelated static integers into a single type, in this case named &#8216;Priority&#8217;.  Second, because enumerations are value types (and thus are allocated on the stack), they require less resources from both the processor and memory on which the application is running.<\/p>\n<p>2) Joe mentioned &#8220;<i>&#8230; you probably need to put a lock{} around the calls to it (StreamWriter) &#8211;it&#8217;s not guaranteed to be threadsafe.<\/i>&#8220;.  Turns out he&#8217;s right (not that it was a surprise).  The <a href=\"http:\/\/msdn.microsoft.com\/library\/default.asp?url=\/library\/en-us\/cpref\/html\/frlrfSystemIOStreamWriterClassctorTopic.asp\">StreamWriter documentation<\/a> has this to say: &#8220;<i>Any public static (Shared in Visual Basic) members of this type are thread safe. Any instance members are not guaranteed to be thread safe.<\/i>&#8221;  But the solution is easier than putting a lock{} on it.  StreamWriter extends the TextWriter class, which itself has a static method for generating a thread safe wrapper.  So where in the first version I had this:<br \/>\n<code><br \/>\nStreamWriter sw = File.AppendText(filePath);<br \/>\n<\/code><br \/>\nI now have this:<br \/>\n<code><br \/>\nTextWriter tw = TextWriter.Synchronized(File.AppendText(filePath));<br \/>\n<\/code><br \/>\nThe File.AppendText() method returns a StreamWriter object, which the TextWriter.Synchronized() method wraps to create a thread-safe TextWriter which can be used just like a StreamWriter.  <\/p>\n<p>3) I noticed that the log4j implementation uses wrapper methods to make the argument list shorter. For instance, the Logger class has methods that look like this:<br \/>\n<code><br \/>\npublic void debug(Object message);<br \/>\npublic void info(Object message);<br \/>\npublic void warn(Object message);<br \/>\npublic void error(Object message);<br \/>\npublic void fatal(Object message);<br \/>\n<\/code><br \/>\nI added the same idiom to my Logger class:<br \/>\n<code><br \/>\npublic static void Debug(String message) {<br \/>\n&nbsp;&nbsp;Logger.Append(message, (int)Priority.DEBUG);<br \/>\n}<br \/>\n<\/code><br \/>\nwhile still allowing for the more verbose:<br \/>\n<code><br \/>\npublic static void Append(String message, int level)<br \/>\n<\/code><br \/>\nI uploaded the source and a test so you all can have a hack at it, if that kind of thing toots your horn:<br \/>\n&middot; <a href=\"\/images\/files\/Logger.cs\">Logger.cs<\/a><br \/>\n&middot; <a href=\"\/images\/files\/TestLogger.cs\">TestLogger.cs<\/a><br \/>\nI&#8217;m *always* open to comments and feedback. If you have even an inkling as to what I could do better with this code, *please* add your thoughts below.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Joe gave me some great feedback on the C# logging utility I wrote about a couple months ago. Per his suggestions, I modified it in the following ways: 1) Instead of using public static int variables as levels, I added an enumeration: enum Priority : int { &nbsp;&nbsp;OFF = 200, &nbsp;&nbsp;DEBUG = 100, &nbsp;&nbsp;INFO = &hellip; <a href=\"https:\/\/cephas.net\/blog\/2003\/10\/26\/logging-in-c-enumerations-thread-safe-streamwriter\/\" class=\"more-link\">Continue reading <span class=\"screen-reader-text\">Logging in C#: enumerations, thread-safe StreamWriter<\/span> <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":[],"categories":[17,2],"tags":[],"_links":{"self":[{"href":"https:\/\/cephas.net\/blog\/wp-json\/wp\/v2\/posts\/529"}],"collection":[{"href":"https:\/\/cephas.net\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/cephas.net\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/cephas.net\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/cephas.net\/blog\/wp-json\/wp\/v2\/comments?post=529"}],"version-history":[{"count":0,"href":"https:\/\/cephas.net\/blog\/wp-json\/wp\/v2\/posts\/529\/revisions"}],"wp:attachment":[{"href":"https:\/\/cephas.net\/blog\/wp-json\/wp\/v2\/media?parent=529"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/cephas.net\/blog\/wp-json\/wp\/v2\/categories?post=529"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/cephas.net\/blog\/wp-json\/wp\/v2\/tags?post=529"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}