Hi.
I'm a student of ADS just like Frances and I have to add that I've learned things from him too.
The notification itself is issued by the server in response to an action as defined on a trigger. The triggers needs to be created only once. In my case, the trigger gets created by the init program that creates a new database or when updating a datadictionary. Here is sample source code to create the trigger from code:
oAdsQuery:cSql += ;
"CREATE TRIGGER [SignalEvent AfterUpdate] ON encounters AFTER UPDATE BEGIN \n" + ;
" DECLARE @EncTotChrgs MONEY; \n" +;
" DECLARE @OldTotChrgs MONEY; \n" +;
" DECLARE @cEncounter CHAR( 13 ); \n" +;
" \n" +;
" SET @EncTotChrgs = ( SELECT EncTotChrgs FROM __new ); \n" +;
" SET @OldTotChrgs = ( SELECT EncTotChrgs FROM __old ); \n" +;
" SET @cEncounter = ( SELECT encounter FROM __new ); \n" +;
" \n" +;
" IF @EncTotChrgs <> @OldTotChrgs THEN \n" +;
" EXECUTE PROCEDURE sp_SignalEvent( \n" +;
" 'EncChrgsUpdated', \n" +;
" True, 2, \n" +;
" @cEncounter + ',' +CAST( @EncTotChrgs AS SQL_CHAR ) );\n" +;
" END; \n" +;
" \n" +;
"END NO MEMOS PRIORITY 1; \n" +;
" \n"
oAdsQuery:Run()
I agree with Frances, it would be much better if you could spawn a new thread only to wait for notifications. xHarbour does not seem to work well with multithreads. However, here is outline of how to listen for notifications from the server without a timer using xharbour background tasks. The code is in production and works well.
//create the event notification using stored procedure sp_createevent()
"EXECUTE PROCEDURE sp_CreateEvent( 'EncChrgsUpdated', 2 ); \n"
...
//wait for events using stored procedure
//this script gets executed inside ListenForMyEventOnBckgrnd().
//We are only initializing here.
::oEventQuery:cSql := " \n" +;
"EXECUTE PROCEDURE sp_WaitForEvent( 'EncChrgsUpdated', 0, 0, 0 ); \n"
...
::nIdle := hb_IdleAdd( {|| hb_BackGroundRun() } )
::hTask := hb_BackGroundAdd( {|| ::ListenForMyEventOnBckgrnd() }, _WAIT, .T. )
...
//this method gets executed on the background by hb_backgroundAdd().
/* This method will listen for a specific ADS notification from the server on the
background. oEventQuery sql statment is defined at the beginin in method :New(). The
specific notification we are interested on is called: EncChrgsUpdated
The only notification from the server that we are interested here
are notifications on new charges begin posted so that the StatusPanel xbrowse
as well as the graphs may be updated on real time.
*/
METHOD ListenForMyEventOnBckgrnd() CLASS StatusPanel
LOCAL aParms := {}
LOCAL nPos := 0
LOCAL lChanged := .F.
LOCAL aLine, nAdd, aRow
::oEventQuery:aResultSet := {}
//Listening timeout is set to zero. Everytime this background method runs
//it will check if a notification has been issued since last check.
::oEventQuery:cAlias := NIL
::oEventQuery:Run()
/*Uncomment the line below to monitor this backgound task working
DEBUG ::oEventQuery:aResultSet /**/
//update and refresh graph + xbrowse grid with new info. :aResultSet contains
//the encounter number and EncTotChrgs amount separated by a comma.
FOR EACH aLine IN ::oEventQuery:aResultSet
aParms := hb_aTokens( aLine[ 3 ], "," )
IF aLine[ 2 ] < 1 .OR. LEN( aParms ) < 2 ;LOOP ;ENDIF
::oUpdtQry:aParameters := { aparms[ 1 ] }
::FetchSPData( ::oUpdtQry )
//::aResultSet should never be empty. This is just a precaution.
IF EMPTY( ::oUpdtQry:aResultSet ) ;LOOP ;ENDIF
IF ( nPos := AScan( ::oAdsQuery:aResultSet, { |e| e[ COL_ENCOUNTERID ] == aParms[ 1 ] } ) ) > 0
::OnUpdateRow( nPos, ::oUpdtQry:aResultSet[ 1 ] ) //, Val( aParms[ 2 ] ) )
ELSE //new Encounter has been inserted into Encounters.adt
::OnInsertRow( AClone( ::oUpdtQry:aResultSet[ 1 ] ) )
ENDIF
lChanged := .T.
NEXT
IF lChanged
::oBrw:Refresh()
::UpdateGraph( .t. )
ENDIF
RETURN NIL
Again, this is fwh + xHarbour 1.2.1 + bcc 5.82 code that works with ADS 10 perfeclty. You can always read the help files and search about ADS notifications system on the devzone to see more detail.
Best regards,
Reinaldo.