S_SERVER_THREAD_INIT

Initialize a thread for xfServer

 

WNSupported in Synergy .NET on Windows

 

 

xcall S_SERVER_THREAD_INIT

Discussion

When using xfServer in a multi-threaded environment, each thread must have a unique connection to xfServer (just as each thread must have a separate connection to an OpenNet server). This is because you cannot perform simultaneous parallel operations on one socket.

If you do not use S_SERVER_THREAD_INIT, the runtime will block parallel operations and your application may appear to hang. All .NET applications are multi-threaded to some extent, because the garbage collector thread runs concurrently with your code. If you have a finalizer on an object that is run by the garbage collector and uses a channel to xfServer, it could be on the same xfServer as another thread currently performing I/O. When using channels, it is important to deterministically close them (including Select class objects) using the dispose pattern. See DATA for more information about the creation of disposable data objects.

Once you have created a new thread and want to establish a thread-specific connection to xfServer, you must call S_SERVER_THREAD_INIT to initialize the thread so a new xfServer connection will occur for channels (and Select or From objects) opened on that thread. Also be sure to close any channels opened after S_SERVER_THREAD_INIT is called on that same thread, before the thread is destroyed.

Important

If a channel opened on a thread used with S_SERVER_THREAD_INIT is used on another thread (for example the garbage collector), a “.NET xfServer client I/O on wrong thread” error ($ERR_WRONGTHREAD) will occur. Ensure you use disposable select objects and close all channels under program control. Do not wait for a garbage collector pass to close a channel or dispose an object that contains a channel.

Call S_SERVER_THREAD_SHUTDOWN on thread termination to ensure the thread connection shuts down and resources are released.

If S_SERVER_THREAD_INIT is called in the main thread or more than once in a thread, an “Invalid operation” error ($ERR_INVOPER) is generated.

Note

There is automatically one xfServer connection per AppDomain.

Examples

The following program shows how to ensure the S_SERVER_THREAD_INIT is called only once when using a .NET thread pool.

import Synergex.SynergyDE.Select
import System.Threading
import System.Collections.Generic
main
    record rec
      key, d5
      dat, a45
    record
      chn, i4
      cnt, int
.define myfile "DAT:myfile.ism@localhost"
proc
    open(15, o, 'tt:')
    xcall delet(myfile)
    xcall isamc(myfile, 50, 1, "s=1,l=5,dups")
    open(chn, u:i, myfile)
    for key from 1 thru 101
      store(chn, rec)
    close(chn)
    for cnt from 1 thru 1000 by 1
    begin
      data snarfObj = new snarf()
      data thread1 = new System.Threading.Thread(snarfObj.doit)
      data thread2 = new System.Threading.Thread(snarfObj.doit)
      thread1.Start()
      thread2.Start()
      thread1.Join()
      thread2.Join()
    end
    Console.WriteLine("sleeping");
    sleep 2                                     ;Wait for all threads to end
    GC.Collect();
    GC.WaitForPendingFinalizers()               ;Ensure all destructors close
                                                ; before deleting file 
    xcall delet(myfile)
                
end  
namespace will
    class snarf
      {ThreadStatic}
      static hasRun, boolean, false
      public method doit, void
        obj, @object
        record rec
          key, d5
          dat, a45
        record
          cnt, i4
          chn, int
        proc
          if(!hasRun)
          begin
            xcall s_server_thread_init
            hasRun=true
          end
          for cnt from 1 thru 10
          begin
            disposable data selobj, @Select, new select(new From(myfile,
  &                    rec, "/io=i:i"), (where)(key.gt.100))
              foreach rec in selobj
nop;
          end
        xcall s_server_thread_shutdown
      endmethod
    endclass
endnamespace