From: JPB on 2 Dec 2009 11:10 Hi, I've also been experimenting with connecting to my server in a separate thread (using the dhRichClient3 thread classes) so that the client app isn't locked while it connects (and auto-reconnects on disconnection) to an RPC listener. The issue that I've run into is that I can't return a CRpcConnection class over the thread handler. To overcome this, I have added an RPC function to the thread object class like so: Public Function Rpc(Dllname As String, ClassName As String, ProcName As String, ParamArray P() As Variant) As Variant Select Case UBound(P) Case -1 Rpc = mo_RpcCnn.Rpc(Dllname, ClassName, ProcName, 5) Case 0 Rpc = mo_RpcCnn.Rpc(Dllname, ClassName, ProcName, 5, P(0)) Case 1 Rpc = mo_RpcCnn.Rpc(Dllname, ClassName, ProcName, 5, P(0), P(1)) 'Case ETC.... ************ End Select End Function And then I call the Rpc method client-side as follows: Debug.Print TH.CallSynchronous("RPC", "ThreadTest.dll", "CTest", "Test", "param1", "param2") This works OK, except that since there is no nice way to pass a ParamArray received from one function to another function (i.e. from the Thread class RPC function to the CRPCConnection RPC function), I will have to have a big SELECT CASE statement - not the end of the world, just ugly. I was just wondering if any of you have tried this previously, and if so, do you have a cleaner solution? Thanks in advance, Jason
From: Schmidt on 2 Dec 2009 13:11 "JPB" <jasonpeterbrown(a)gmail.com> schrieb im Newsbeitrag news:3c31c0ba-8940-40b1-9d8c-be718522d269(a)h10g2000vbm.googlegroups.com... > I've also been experimenting with connecting to my server in a > separate thread (using the dhRichClient3 thread classes) so that the > client app isn't locked while it connects (and auto-reconnects on > disconnection) to an RPC listener. The very first connect on an encrypted connection takes about 0.5- 1 sec (due to the Diffie-Hellman key-exchange and the required math on large primes) - but subsequent connects on such an encrypted connection should work fast IMO. The normal (unencrypted) connects are working much faster, depending only on the normal socket-performance and the type of the LAN. So, I would carefully decide, if you really want to introduce such an additional thread-layer, since you seem to perform all your RPC-Calls over the thread synchronously in either case. But putting the clientside RPCObject into its own thread has also benefits of course, since all the compression/ decompression + encryption/decryption on the "socket- ByteArrays" is done on a different CPU-Core then. And you get the opportunity, to call certain "long-runner" RPCs in an asynchronous fashion later on as well. [Wrapping the RPC-Call in a similar function-construct] > Public Function Rpc(Dllname As String, ClassName As String, ProcName > As String, ParamArray P() As Variant) As Variant > Select Case UBound(P) > Case -1 > Rpc = mo_RpcCnn.Rpc(Dllname, ClassName, ProcName, 5) > Case 0 > Rpc = mo_RpcCnn.Rpc(Dllname, ClassName, ProcName, 5, P(0)) > Case 1 > Rpc = mo_RpcCnn.Rpc(Dllname, ClassName, ProcName, 5, P(0), P(1)) > 'Case ETC.... ************ > End Select > End Function > > And then I call the Rpc method client-side as follows: > > Debug.Print TH.CallSynchronous("RPC", "ThreadTest.dll", "CTest", > "Test", "param1", "param2") > > This works OK, except that since there is no nice way to pass a > ParamArray received from one function to another function (i.e. from > the Thread class RPC function to the CRPCConnection RPC function), > I will have to have a big SELECT CASE statement - not the end of the > world, just ugly. I was just wondering if any of you have tried this > previously, and if so, do you have a cleaner solution? Such a cascade looks "ugly" (or not, depending on ones "appreciation for symmetries" <g>), but it's the usual approach - and not that costly in terms of performance. I write it usually this way, to have a better look at potential copy/paste-errors regarding the Index-numerations: Select case Ubound(P)+1 case 0: Result = SomeFunc(A, B, C) case 1: Result = SomeFunc(A, B, C, P(0)) case 2: Result = SomeFunc(A, B, C, P(0), P(1)) case 3: Result = SomeFunc(A, B, C, P(0), P(1), P(2)) etc... In case of a LateBound-Call to a method of a given (As Object) ClassInstance one could spare the calling-cascade, using Eduardo Morcillos OleLib.tlb and performing the IDispatch-Call directly (using Pointers) - that's what I'm doing internally in the serverside RPC- WorkerthreadClasses, if these have to call the serverside Dll- Functions. But you have an early-bound call-delegation here - and the cascade is IMO the easiest and fastest way. Olaf
From: JPB on 2 Dec 2009 16:05 On Dec 2, 1:11 pm, "Schmidt" <s...(a)online.de> wrote: > The very first connect on an encrypted connection takes about 0.5- > 1 sec (due to the Diffie-Hellman key-exchange and the required > math on large primes) - but subsequent connects on such an > encrypted connection should work fast IMO. > The normal (unencrypted) connects are working much faster, > depending only on the normal socket-performance and the > type of the LAN. > > So, I would carefully decide, if you really want to introduce > such an additional thread-layer, since you seem to perform > all your RPC-Calls over the thread synchronously in either case. I'm not so much concerned about the time for successful connections as you are right that they do happen quite fast. Although, my connection process takes longer because of my unusual Credentials/Business server connection process mentioned in previous posts. Essentially, a "successful" connection can take up to 3 connections (including 1 failed connection which can take some time to timeout) before the UI is handed back to the users. I've also put in place an auto-reconnect feature that will continually try to reconnect the client to the server (say, every 30 seconds or so) when the connection has gone down for whatever reason (Network problems, admin killed the service temporarily, etc...). Because I do cache some things client-side, users can still do some productive work without the RPC server being available, so it would be a nice feature not to have to lock them out every time the auto-connection feature kicks in. I also just like the strides I've been able to make in UI responsiveness thanks to your threading classes, and I'm getting very picky about UI freezes :) For example, I have a network printer that is sometimes not available (for example, if I am out of office). Some other applications that I use will freeze for up to thirty or so seconds before they timeout if that printer happens to be my default printer (and this is just to open the program in some cases!). Thanks to the dhRichclient3 thread classes, I am able to run the scan for online printers in a separate thread, and update the UI accordingly - so the UI stays continuously responsive no matter what is going on with the printers. > But putting the clientside RPCObject into its own thread > has also benefits of course, since all the compression/ > decompression + encryption/decryption on the "socket- > ByteArrays" is done on a different CPU-Core then. > And you get the opportunity, to call certain "long-runner" > RPCs in an asynchronous fashion later on as well. That is a bonus that I did not consider. > Such a cascade looks "ugly" (or not, depending on ones "appreciation > for symmetries" <g>) True! I guess it feels ugly more than it looks ugly ;) > In case of a LateBound-Call to a method of a given (As Object) > ClassInstance one could spare the calling-cascade, using Eduardo > Morcillos OleLib.tlb and performing the IDispatch-Call directly (using > Pointers) - that's what I'm doing internally in the serverside RPC- > WorkerthreadClasses, if these have to call the serverside Dll- > Functions. > But you have an early-bound call-delegation here - and the cascade > is IMO the easiest and fastest way. Thanks for the advice again. Since I'm already going through a couple of layers, I think that I will go with the fastest way. Jason
|
Pages: 1 Prev: Windows Mobile 2003 development in VB6 Next: upgrading common controls v5 to v6 |