Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>Hey there. Had a quick look, and while it appears to be thread-safe, I don't believe it is particularly optimal. I would suggest a solution along these lines</p> <p><strong>NOTE:</strong> just read the other responses. What follows is a fairly optimal, optimistic locking solution based on your own. Major differences is locking on an internal class, minimizing 'critical sections', and providing graceful thread termination. If you want to avoid locking altogether, then you can try some of that volatile "non-locking" linked list stuff as @Vitaliy Lipchinsky suggests.</p> <pre><code>using System.Collections.Generic; using System.Linq; using System.Threading; ... public class Logger { // BEST PRACTICE: private synchronization object. // lock on _syncRoot - you should have one for each critical // section - to avoid locking on public 'this' instance private readonly object _syncRoot = new object (); // synchronization device for stopping our log thread. // initialized to unsignaled state - when set to signaled // we stop! private readonly AutoResetEvent _isStopping = new AutoResetEvent (false); // use a Queue&lt;&gt;, cleaner and less error prone than // manipulating an array. btw, check your indexing // on your array queue, while starvation will not // occur in your full pass, ordering is not preserved private readonly Queue&lt;LogObj&gt; _queue = new Queue&lt;LogObj&gt;(); ... public void Log (string message) { // you want to lock ONLY when absolutely necessary // which in this case is accessing the ONE resource // of _queue. lock (_syncRoot) { _queue.Enqueue (new LogObj (DateTime.Now, message)); } } public void GetLog () { // while not stopping // // NOTE: _loggerThread is polling. to increase poll // interval, increase wait period. for a more event // driven approach, consider using another // AutoResetEvent at end of loop, and signal it // from Log() method above for (; !_isStopping.WaitOne(1); ) { List&lt;LogObj&gt; logs = null; // again lock ONLY when you need to. because our log // operations may be time-intensive, we do not want // to block pessimistically. what we really want is // to dequeue all available messages and release the // shared resource. lock (_syncRoot) { // copy messages for local scope processing! // // NOTE: .Net3.5 extension method. if not available // logs = new List&lt;LogObj&gt; (_queue); logs = _queue.ToList (); // clear the queue for new messages _queue.Clear (); // release! } foreach (LogObj log in logs) { // do your thang ... } } } } ... public void Stop () { // graceful thread termination. give threads a chance! _isStopping.Set (); _loggerThread.Join (100); if (_loggerThread.IsAlive) { _loggerThread.Abort (); } _loggerThread = null; } </code></pre>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload