S_SERVER_THREAD_INIT
Initialize a thread for xfServer
|
|
|
|
NSupported in Synergy .NET
|
xcall S_SERVER_THREAD_INIT
|
|
The S_SERVER_THREAD_INIT routine is deprecated in Synergy 12.1.1 and higher. We recommend using %CREATE_SERVER_CONNECTION instead. |
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
