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.
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.
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