[C#] Which System.Threading class to use?

Caporegime
Joined
18 Oct 2002
Posts
29,493
Location
Back in East London
The scenario:

I have a file writer that is accessed by many processes/threads, so I have to implement a queue for lines in case the file is locked. So I also have a thread that watches over the contents of the queue, and writes to disk at the first available chance.

To save performance, I Suspend() the thread when no items are in the queue, and Resume() when there are.

However, Suspend() is deprecated, and the suggestions are Mutex, Monitor, Semaphore or Event.

Which should I use?

TIA.
 
No, just a bog standard Queue. I've synchronised the thread that is writing to file. It works just fine, but I've noticed the deprecated warning and wanted to resolve it :)
 
Ok, I'm looking through the API's and I'm still unsure.. infact, unsure if it's even necessary anymore.. here is paraphrased what I have already.. after clearing up a bit from using a while (true) loop..

Code:
public void addMessage (string msg)
{
  this.queue.Enqueue(msg);
  this.StartThread();
}

[MethodImpl(MethodImplOptions.Synchronized)]
public void StartThread()
{
  if (this.thread == null || !this.thread.IsAlive)
  {
    this.thread = new Thread(WriteQueueToFile);
    this.thread.Start();
  }
}

private void WriteQueueToFile()
{
  try {
    StreamWriter sw = new StreamWriter(this.Path);
    while (this.queue.Count > 0) {
      sw.WriteLn((string)this.queue.Dequeue());
    }
    sw.Flush();
    sw.Close();
  }
  catch (IOException e)
  {
    // do nothing
  }
}
 
Can a thread Start() after, for example, Abort() is called?

The intention was that it is only instantiated if it's not already set and active.
 
Seriously, that's your implementation?

Without seeing what's in your queue class it's hard to be sure exactly what's going to happen, but I can definitely see potential for it to go wrong, most probably by ending up with items left in the queue as the thread exits. OK not a massive problem but you still have the potential to lose data if the application is shut down before another call to the addMessage method.

You need to be acting on changes to the queue itself (or another variable, maybe just a count of current items to process) rather than adding to the queue and then calling the StartThread method. You also need to check that the Enqueue method is thread safe or you'll probably endup with messages going missing there too (or at least have an opportunity for them to).

Another smaller problem with your code is you're not handling exceptions well enough, you have potential there to lock the file open if an exception is thrown when writing. Either close the writer in a finally block, or use a using statement.

Quite honestly, you seem to know just enough about this to cause yourself some major headaches.


Mick.
Is that enough smug for now?

I've already posted elsewhere that I've only been using C# for a week, and thus threads like this. Anyway.. Instead of threadsafing the Enqueue method (which is an instance of System.Collections.Queue) I'll synchronise the addMessage().

As for basing it on an event or changes, that's what I was hoping as an answer to this thread.. oddly enough.. given why I'm asking in the first place.

This is one reason I prefer Smalltalk.. I don't have to faff with types, thread safe this or that, or any shenanigans, because the underlying framework doesn't let these problems bubble up like .NET or Java does.

As for the StreamWriter.. it's handle would be closed after exiting the method, surely? Or are you telling me the garbage collection is that poor in .NET?
 
Last edited:
I'm not trying to be smug at all, I'm just telling you there are problems. I also get sick to death of people asking for help on this forum, then totally ignoring the advice they're given!


Well sorry? I've not seen you post saying you've only been using C# for a week, do I have to do a background check on you before replying to any threads?


Why, so that you can use the same queue class somewhere else in a non threadsafe way? What's the benefit of this?

/EDIT: after reading that bit again, OK fair enough, I'd still look at having a custom class for it though which was threadsafe.


If you look back, I gave you an answer which you then totally ignored.


Mick.
I didn't ignore your advice, I replied with "I can't make things wait" and "It's the standard Queue" as in, it's the System.Collections.Queue class that I can't amend, I could override, granted, but surely this is not necessary if I synch() the addMessage() method which is the only public accessor to the queue, and there is only one instance of the class for each file. I have implemented a registry of file accessors, deliberately so because "one file - one accessor" just makes sense.

Locking the filewriter.. so that would be the StreamWriter or the whole thing (for clarification)? I don't see the advantage to this:

I can't afford to make the processes/threads wanting to access this file wait - it's just not an option due to the amount of work involved to allow them to wait (out of my hands.. it's VB6 stuff which was written by other people many moons ago :ugh: )

This is why I have a queue, to buffer messages until the stream/file is accessible.

What I have there already works, and hasn't had any issues with 150,000 messages per minute, for a week.

As for using a monitor.. I'm still unsure how that will help? The examples of Monitor I can find are all to do with blocking others acessing - I don't want blocking, I want Sleep()ing when the queue is empty, to save those critical cpu cycles. :)
 
Ok, well to start, things are never written to the file in batch - so that's a non-issue (for the foreseeable anyway).

To answer the question of "How can I be sure all messages are being sent" it's because we have a parsing application that flags alerts when things are missed out on. :)

And that's using the old version (not even that of what I've made in this thread) :)

My next question, and I'm being too lazy to just test it, can a thread that has finished execution (normally, not Abort() or exception) be Start()ed?
 
So an object does not get garbage collected when it's reference counter reaches <1 ? :/

OK, I'll add Dispose(); or Close(); to the method when it's finished.
 
Smalltalk manages it without loss of performance. So I don't see why CLR can't. But nevermind, this will only end in an evangelical war.

Thanks for the info.
 
Back
Top Bottom