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.
Like I said, fair enough, sync the addMessage method.
Locking the filewriter.. so that would be the StreamWriter or the whole thing (for clarification)? I don't see the advantage to this:
I said that was an option if you weren't bothered about each thread having to wait for it's turn. But what you'd do is have any variable object and do lock(var) { code to write here }, that'd be the simplest implementation of this class, but as said each thread would have to wait.
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: )
Yeah, don't make them wait then.
This is why I have a queue, to buffer messages until the stream/file is accessible.
Yep fine.
What I have there already works, and hasn't had any issues with 150,000 messages per minute, for a week.
Are you sure about that? Can you be sure every single message has been written?
Like I said, the most likely event is that some messages will wait until the next addMessage call before being written if the call to addMessage happens to after the loop but before the thread has completed, not a massive problem unless your program exists with a message still in the queue. Could easily be fixed by forcing each queue to be written after anything calling the addMessage has finished but before exiting the program.
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.
What exactly do you think the thread is going to be doing while it's monitoring that variable but not writing? I'd argue you'll probably be wasting more CPU cycles by forcing creating a new thread everytime you want to do some writing of the message queue to file.
Look
here for something similar to what I mean (although it's more an example of using delegates).
The easiest way to get this safe based on what you've said though is just to make access to the queue threadsafe, remember you need to lock the variable when adding to the queue and when getting the count/popping the last item from it for it to be safe. Probably easiest to write a couple of methods to wrap around the Enqueue, Dequeue and Count of the queue and use them instead of accessing them directly.
Maybe something like (no idea if this builds but you should get the idea):
Code:
private bool QueueHasItems
{
get
{
lock(queue)
{
return (this.queue.Count > 0);
}
}
}
private void Push(string msg)
{
lock(queue)
{
this.queue.Enqueue(msg);
}
}
private string Pop()
{
lock(queue)
{
return (string)this.queue.Dequeue();
}
}
private void WriteQueueToFile()
{
try
{
using (StreamWriter sw = new StreamWriter(this.Path))
{
while (QueueHasItems) {
sw.WriteLn(Pop());
}
}
}
catch (IOException e)
{
// do nothing
}
}
Obviously using the Push method to add to the queue.
Mick.