Hi,
Yet another question relating to the CSLA 1.x BatchQueue components!
I have implemented a Windows service to process BatchJobRequests on a transactional MSMQ queue. When I start the service with a message already on the queue, the BatchJobRequest gets picked up and processed as it should (I have implemented a console app to step through the code).
However, if I subsequently send another BatchJobRequest to the queue it just sits there and is never processed. I've looked at the code, and this would seem to be because the Timer is never re-started because of the condition in the code below (in non-bold text) - which means that the MonitorQueue stays in the WaitOne state - it never gets notified by the Timer that it should poll the queue.
I have modified the code in the BatchQueueService.ScanQueue() method as follows (bold text is my added code):
if(nextWake < DateTime.MaxValue && nextWake > DateTime.Now)
{
// we have at least one entry holding, so set the
// timer to wake us when it should be run
_timer.Interval = nextWake.Subtract(DateTime.Now).TotalMilliseconds;
_timer.Start();
}
else
{
_timer.Start();
}
And now, unless a nextWake time is specified, the queue is polled continuously every 100 milliseconds (which is the default poll interval).
Does this seem right? Should it be necessary to do this, and have I done this correctly?
As ever, any help is much appreciated.
Chris
generally if I want to setup a service to do stuff I start with a layout kinda like this:
While(true && (!_ShutDownFlag)){
// Do Stuff Here
If (X)
break;
else
Thread.Sleep( _SleepTime );
}
this is in a method that init's the loop and is started by using the Threading / start a new thread stuff in .net
the SleepTime and ShutdownFlag are defined in the main code and let other logic control the loop and exit.
where I put "Do STuff" that's generaly a few calls to methods that are only called by that thread to do the work and as they finish the loop keeps going.
if I am using .Net 2.0 I use the backgroundworker as it does most of the setup work.
Chris,
Here's what I did... Below is first pass (almost hack) and I'll look at it again later. I will be looking at this again because I'm concerned that the batch server will not wake up when something is in the queue with a future run date and something else is added.
At the end of the Start() routine:
' == added
AddHandler mQueue.PeekCompleted, AddressOf mQueue_PeekCompleted
mQueue.BeginPeek() ' wait for something to arrive
End Sub
#Region " Fire when new msg arrives in empty queue"
Private Shared Sub mQueue_PeekCompleted(ByVal sender As Object, ByVal e As System.Messaging.PeekCompletedEventArgs)
Try
mQueue.EndPeek(e.AsyncResult)
mSync.Set()
' mQueue.BeginPeek()
Catch ex As Exception ' if we are waiting when the program ends, we get an exception
End Try
End Sub
#End Region
And at the bottom of the ScanQueue() routine:
' -- added
If nextWake = Date.MaxValue Then
' nothing in queue, just wait for something to arrive
mQueue.BeginPeek()
End If
End Sub
It accomplishes the same basic thing, but I didn't want to keep polling to check the queue. When I get back to this, I will fix so that if something is in the queue, I poll ever 5 seconds or so.
Brad
PS: I'm doing this because I built a ReadOnly business object to store jobs directly into the queue without going through the TCP channel. (Less to configure)
Copyright (c) Marimer LLC