Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

receiving message in nightly batch process

350 views
Skip to first unread message

mjp...@gmail.com

unread,
Aug 24, 2006, 1:32:18 PM8/24/06
to
I want to have a console program that runs once every night to process
messages that were recieved in the queue during the day. All the online
examples I can find just show how to either receive a single message or
implement a constant-running listener service. What is the best way to
read all receive all messages and process them at once? I am using c#.

Thanks

sloan

unread,
Aug 24, 2006, 4:18:54 PM8/24/06
to

You can write a windows service.

The key/trick is that you can have a timer... which fires and does the work.
The timer has a "dueTime" and "intervalTime". By manipulating these values.
you can get the service to fire once a night.

But you'll have to do a little math.
Lets say you want it to start at midnight.
But the windows service "starts up" at 4:10 pm (whenever the computer
reboots or etc)

So you have to do some math to say "I need to dueTime to be in 7hrs and 50
minutes"
(midnight subtract the current time of 4:10pm)
Then you can set the interval to 24 hours.

That way.... it will always fire at midnight....

That's ~a way. I don't know if its the best way.

Here is some code. Its from way back, and in vb.net. Before my company's
conversion. But should give you an idea.

#1 Here is the xml I 'm using. Notice that 86400000 is the number of ms in 1
day.

<?xml version="1.0"?>
<root>
<data>
<services>
<service nameof="beep" active="1" interval_milliseconds="12000"
start_time=""/>
<service nameof="my_service_name" active="1"
interval_milliseconds="86400000" start_time="4:09 PM"/>

</services>
</data>
</root>


Here is the class to do the math...... based on the XML.

Public Class FeaturesEnabled

Private xmlDoc As New System.Xml.XmlDocument()

Private boolBeepServiceIsEnabled As Boolean

Private lngBeepServiceIntervalMilliseconds As Long

Public Function GetDueTime(ByVal strServiceName As String) As Long

Const LNG_DEFAULT_DUE_TIME As Long = 30000

Dim t1 As DateTime

Dim t2 As DateTime

Dim lngMinutesDifference As Long

Dim lngDueTime As Long

Dim strCurrentServiceStartTime As String

Select Case strServiceName

Case "my_service_name"

' (this special call will set the service to run at an EXACT Time, instead
of

' when the the main monitoring service is started ..

' this is Good for long running procedures.

'THIS IS A SPECIAL CASE BECAUSE my_service_name is such a long running
procedure to be done offhours

'That It NEEDS to start at a specific time (an OFF HOURS TIME)

'get the TIME from the xml

strCurrentServiceStartTime =
(xmlDoc.SelectSingleNode("//root/data/services/service[@nameof='" &
strServiceName & "']/@start_time").Value)

If Len(strCurrentServiceStartTime) <= 0 Then

'default safety

strCurrentServiceStartTime = "12:00 AM"

End If

t2 = Date.Now

t1 = CDate(Date.Today.ToShortDateString & " " & strCurrentServiceStartTime)

lngMinutesDifference = (DateDiff(DateInterval.Minute, t2, t1))

If lngMinutesDifference > 0 Then

lngDueTime = lngMinutesDifference * 60 * 1000 ' take the minues and do the
math to get the milliseconds

ElseIf lngMinutesDifference < 0 Then

' the next line will set the delay time to the NEXT occurence of the time

lngDueTime = ((24 * 60) - lngMinutesDifference) * 60 * 1000

Else

lngDueTime = 0

End If

GetDueTime = lngDueTime

EventLogWriter.WriteEventLogEntry(UCase(strServiceName) & " DELAY period set
to : " & lngDueTime & vbCrLf & (lngDueTime / (1000 * 60 * 60)) & " hours" &
vbCrLf & vbCrLf & t1.ToString & vbCrLf & t2.ToString,
EventLogEntryType.Information)

Case Else

GetDueTime = LNG_DEFAULT_DUE_TIME

End Select

End Function

Public Function GetBeepServiceIntervalInMilliSeconds()

GetBeepServiceIntervalInMilliSeconds = lngBeepServiceIntervalMilliseconds

End Function

Public Function GetBeepServiceIsEnabled() As Boolean

GetBeepServiceIsEnabled = boolBeepServiceIsEnabled

End Function

Public Sub New()

'some default values

lngBeepServiceIntervalMilliseconds = 3000

Dim strCompletePathFileXMLFileName As String

strCompletePathFileXMLFileName = ( find the xml file some how )

xmlDoc.Load(strCompletePathFileXMLFileName)

boolBeepServiceIsEnabled =
((xmlDoc.SelectSingleNode("//root/data/services/service[@nameof='beep']/@act
ive").Value) <> 0)

Try

lngBeepServiceIntervalMilliseconds =
(xmlDoc.SelectSingleNode("//root/data/services/service[@nameof='beep']/@inte
rval_milliseconds").Value)

Catch

'Just use defaults if anything fails, aka, no "catching" (aka, see its
declaration above)

End Try

End Sub

End Class

Finally:::::::::::::::::::
This code is what wires up some method ... to when the timer fires.


/*
//'Member Variables
Private feFeaturesEnabled As FeaturesEnabled ' used to encapsulate which
"services inside of this main service" are running
Private timBeepServiceTimer As Timer
*/
Private Sub BeepSetup()

Dim lngDueTime As Long

Dim lngPeriod As Long

' DUE TIME looks like it is the DELAY time .. from the time the service
starts,

' Until this specfic TIMER kicks in. So a Delay Time of 20000

' Will DELAY this timer shooting off until 20 seconds (20000 ms) after the
service starts

lngDueTime = feFeaturesEnabled.GetDueTime("")

lngPeriod = feFeaturesEnabled.GetBeepServiceIntervalInMilliSeconds()

' the magic bullet, notice the part after "AddressOf", which is the method

Dim timerDelegate = New TimerCallback(AddressOf BeepClass.GoBeep) ''
BeepClass.GoBeep is a class with a static/shared method "GoBeep". Here you
would your msmq listener.

timBeepServiceTimer = New Timer(timerDelegate, Me, lngDueTime, lngPeriod) ''
so you're saying... I want to time to start at midnight (using the
calculated dueTime and period ......

End Sub

I think even thru the average vb.net code what is going on.
Outside of coding up the EventHandler's (AddressOf vs += new
EventHandler() ).. the translation should be easy enough.

Here is the simple BeepClass


Public Class BeepClass

Public Shared Sub GoBeep(ByVal state As Object)

Beep()

End Sub

End Class


Check out
http://msmvps.com/blogs/manoj/archive/2005/10/16/70979.aspx

for a good async msmq processor.

<mjp...@gmail.com> wrote in message
news:1156440738.7...@b28g2000cwb.googlegroups.com...

Frank Boyne

unread,
Aug 24, 2006, 6:11:47 PM8/24/06
to
<mjp...@gmail.com> wrote in message
news:1156440738.7...@b28g2000cwb.googlegroups.com...

Just call Receive() within a loop to process the messages one at a time and
use TimeSpan to specify a time limit of some arbitrary amount (say 1
second). When the Receive call throws an IOTimeout exception you can assume
the queue is empty and so you have processed all the messages in the queue.
For example

static void Main(string[] args)
{
MessageQueue queue = new MessageQueue(@".\testQueue");

// set up other queue attributes as necessary

System.Messaging.Message msg = null;

try
{
while (true)
{
msg = queue.Receive(new TimeSpan(0, 0, 1));

// process msg contents
}
}
catch (MessageQueueException mqe)
{
if (mqe.MessageQueueErrorCode == MessageQueueErrorCode.IOTimeout)
{
// Do nothing queue is just empty
}
else
{
// unexpected exception
throw;
}
}
}


mjp...@gmail.com

unread,
Aug 24, 2006, 9:22:35 PM8/24/06
to
Thank you Frank! That's exactly what I needed. I knew there had to be a
simple solution, and that will work.
0 new messages