Setting an event receiver in oxygen

(DonaldShimoda) #1

Have a Delphi server raising RO events.

Oxygen Fire client need to register to that events.

Any sample code to start to work on it?

Best regards.

(antonk) #2


What is the client app platform? .NET or native Mac/iOS ?

(DonaldShimoda) #3


(antonk) #4

Here’s the sample (actually it is shipped with RO SDK): (151.1 KB)

Events concepts (like difference between super- and simple channels) are explained in this article:

(DonaldShimoda) #5

As the project is not form based, but console I use a slight different codea and down work.
I search all the post and documentation and can’t find the reason, so I must ask what is wrong?

BTW, using Json message Delphi Server raises an AV. Using BIN message it work but never get events.
I test on water and Fire, same result.

My client app code:

Class = public class (ITerminalPosServerEvents)
    eventReceiver : RemObjects.SDK.EventReceiver;
    eventChannel  : IClientChannel;
    eventMessage  : IMessage;
    method doRegisterforEvents;
    method OnTerminalPOSDataReceived(PosTerminal: TPosTerminal);
method aClass.doRegisterforEvents;
  //manejo de eventos
  self.eventReceiver  := new RemObjects.SDK.EventReceiver();
  self.eventChannel := ClientChannel.ChannelMatchingTargetUri(_global_server_url);
  self.eventMessage := Message.MessageMatchingTargetUri(_global_server_url);

  if  self.eventMessage is BinMessage then
    var aEnvelope := new AesEncryptionEnvelope(_global_AES_key);
    (self.eventMessage as BinMessage).EnforceMaxMessageSize := false;
    (self.eventMessage as BinMessage).Envelopes.Add(aEnvelope);
    (self.eventMessage as BinMessage).Envelopes[0].Enabled := true;

  self.eventChannel.TargetUrl := _global_server_url;

  self.eventReceiver.Channel := self.eventChannel;
  self.eventReceiver.Message := self.eventMessage;
  //self.eventReceiver.SynchronizeControl := self;
  //self.eventReceiver.OnPollIntervalChanged += new System.EventHandler(@self.eventReceiver_OnPollIntervalChanged);
  //self.eventReceiver.OnPollException += @self.eventReceiver_OnPollException;

  CoService.Create(eventMessage, eventChannel).RegisterMe;
  if eventReceiver.Active then
    writeLn('event receiver enabled guit cliente id ' + self.eventMessage.ClientID);

method aClass.OnTerminalPOSDataReceived(PosTerminal: TPosTerminal);
  writeLn('PosTerminal ' + PosTerminal.Number.ToString + ' status ' + PosTerminal.Status.ToString + ' text ' + PosTerminal.DataReceived );
(antonk) #6

This is a console client to the chat server I’ve posted above: (33.3 KB)

That said, you code looks correct, assuming you do call the doRegisterforEvents method in the constructor (the code snippet misses its code).

A sidenote and a thing you should be aware of (note that this is NOT Elements-specific, it is just how the .NET runtime works):

As you know .NET uses Garbage Collector to recycle objects that are not accessible anymore. Now look at this code:

class method Main(args: array of String): Int32;
  var listener := new ConsoleEventReceiver();


As you can see here a local listener variable is used. So what would happen if we’ll start this console app and will let it run for, say, hours? In DEBUG mode it would run as you’d expect: the listener instance would receive events and so on. Still in RELEASE mode it is quite possible that at some moment of time the listener instance will be killed. This happens because the last 2 lines of the method body do not reference the listener at all, so GC thinks that it is not needed anymore and can be recycled.

This is a hard to catch behavior you should be aware of

(DonaldShimoda) #7

Ok, but how to avoid that? How to avoid the listener to be killed? Any way to tell GC not to release that object?

(antonk) #8

F.e. in the sample I sent to you I’ve assigned the listener to a class field.
Another option is to add the unsubscribe method and to call it at the very end of the Main method