KNOWLEDGE BASE
Log In    |    Knowledge Base    |    4D Home
Tech Tip: Synchronize Async Socket Initialization in Shared Classes
PRODUCT: 4D | VERSION: 20 R | PLATFORM: Mac & Win
Published On: November 6, 2025
When creating UDPSocket instances via CALL WORKER in a shared class constructor, the main thread continues immediately. Using the sockets before the worker completes can lead to undefined behavior like blocked callbacks (e.g., onData) or socket creation failure.

Use a Shared object and Signal to block safely until socket creation finishes

Benefits
  • Sockets are fully initialized before any use.
  • No race conditions in shared class workflows.

Code Example

//Class : MyUDP

property listener : 4D.UDPSocket
property sender : 4D.UDPSocket
property Port : Integer



shared Class constructor($options : Object)

   This.Port:=(OB Is defined($options; "port")) ? OB Get($options; "port") : 32154

   var $socketHolder : Object := New shared object()

   Use ($socketHolder)
      $socketHolder.listener := Null
      $socketHolder.sender := Null
      $socketHolder.endOfInitialization := New signal
   End use

   CALL WORKER("SocketWorker"; Formula($1._initSockets($2)); This; $socketHolder)

   $socketHolder.endOfInitialization.wait() // Wait for sockets to be ready

   This.listener := $socketHolder.listener
   This.sender := $socketHolder.sender


//Class function
Function _initSockets($socketHolder : Object)
   Use ($socketHolder)
       $socketHolder.listener:=4D.UDPSocket.new(This.Port; This)
       $socketHolder.sender:=4D.UDPSocket.new(0; This)
   End use
   $socketHolder.endOfInitialization.trigger()