What is the best method for creating a static class that uses threads?

Let's say I'm designing a simple logging class (yes - I know there are those that already exist in the wild!), And I want the class to be static, so the rest of my code can call it without creating it first. Maybe something like this:

internal static class Log { private static string _logFile = ""; internal static void InitializeLogFile(string path) { ... } internal static void WriteHeader() { ... } internal static void WriteLine(params string[] items) { ... } } 

Now I want the internals to deploy their own thread and run it in Asynch style, perhaps using BackgroundWorker to make things easier. Should I just create a new BackgroundWorker in each method, create a static BackgroundWorker as a private property of a static class, or something that I don’t notice at all?

+4
source share
5 answers

Good call

You definitely want logging to be done in a separate thread as logging code. For example, access methods (for example, "logEvent (myEvent)") should not block file I / O, while the log records the event in the file.

Make the queue so that accessors simply insert items into the queue. Thus, your code should not be blocked while it is trying to register an event.

Run the second thread to empty the internal event queue. This thread can run on the static private method of your log class.

A performance flaw occurs when you try to secure threads in an event queue. You will need to get a lock in the queue every time before popping or clicking on the queue.

Hope this helps.

0
source

You definitely don't want to deploy a new thread or BackgroundWorker every time you call methods. Here I would use the producer-consumer pattern. As it turned out, this is such a general model that Microsoft provided us with the BlockingCollection class, which greatly simplifies the implementation. The best part about this approach is that:

  • only one extra thread required
  • Log methods will have asynchronous semantics
  • temporary ordering of log messages is maintained.

Below is the code to get started.

 internal static class Log { private static BlockingCollection<string> s_Queue = new BlockingCollection<string>(); static Log() { var thread = new Thread(Run); thread.IsBackground = true; thread.Start(); } private static void Run() { while (true) { string line = s_Queue.Take(); // Add code to append the line to the log here. } } internal static void WriteLine(params string[] items) { foreach (string item in items) { s_Queue.Add(item); } } } 
+2
source

You want to have only one thread in the / db log file. Otherwise, the order of the items in the log is unreliable. Have a background thread that pulls out of the stream queue and writes.

+1
source

I think my recommendation is not quite what you expect, but I hope this is somehow useful:

  • Do not use a static class. Instead, use a regular class and hold one instance of it ( singleton pattern ); using dependency injection engine helps this (I use MS Unity and it works fine). If you also define an interface for your logging class, your code will be much more tested.
  • As for piercing material, if I understand that you want logging work that needs to be done in separate streams. Are you sure you really need it? The logger should be light enough so that you can just call the "Write" methods and expect your application to not suffer performance.

One final note: you specify the BackgroundWorker class, but if I'm not mistaken, this class is intended for use with desktop applications, not ASP.NET. In this environment, you should probably use something like the ThreadPool class .

Only my 2 euro cents ...

0
source

I myself created a thread safe logging class. I used it something like this.

 Logging obj = new Logging(filename); Action<string> log = obj.RequestLog(); 

RequestLog will return an anonymous method that wrote in turn. Since Q is thread safe for 1 reader / writer, I did not need to use any locks when calling the log ()

The actual logging object will create a new thread that will run in the background and periodically check all queues. If Q had a string, it would write it to the buffer stream.

I added a little extra code to the read stream, so for each pass that he made in the queues, if nothing was written, he will sleep an additional 10 ms, up to a maximum of 100 ms. Thus, the thread was not too wet. But if heavy writing would occur, he would interview Qs every 10 meters.

Here is the snpit return code for the requested queue. "This.blNewData = true" was such that I did not need to check every Q to see if any new data was recorded. No blocking is associated because the false positive still did not work, since all Qs would still be empty.

OutputQueue was a list of queues that I looped to find out if anything was written. The code to scroll through the list was blocked when NewQueueLog () was called and caused the list to resize.

 public Action<String> NewQueueLog() { Queue<String> tmpQueue = new Queue<String>(32); lock (OutputQueue) { OutputQueue.Add(tmpQueue); } return (String Output) => { tmpQueue.Enqueue(Output); this.blNewData = true; }; } 

In the end, logging was blocked, which helped when many threads were written.

0
source

Source: https://habr.com/ru/post/1338904/


All Articles