RTC Forums

Subscription => Support => Topic started by: Director on February 20, 2010, 10:01:12 AM



Title: Problem with Disconnect method
Post by: Director on February 20, 2010, 10:01:12 AM
Hi.
I uploaded simple example - http://rapidshare.com/files/353208371/Test.rar.html
In this test app I start to connect RtcHTTPClient to unavailable address. All RtcHTTPClient.Reconnect options sets to True.
Problem: I can't normally disconnect RtcHTTPClient when I notice that server address is unavailable.

I found 2 ways for disconnecting:

1. Simply call Disconnect. In this case RtcHTTPClient continues reconnects. Here is an application log:
Code:
Connect clicked
ConnectFail
Reconnect
Disconnect 1 clicked     <<=====     I pressed "Disconnect 1" button
ConnectFail     <<=====     this event triggered right after "Disconnect 1" button pressing
Reconnect
ConnectFail
Reconnect
ConnectFail
...     <<=====     reconnects are proceed...

2. Before call Disconnect I set all RtcHTTPClient.Reconnect options to False. In this case I found 2 variants:
2.1. I press "Disconnect 2" button after Reconnect trigger. All is ended well, RtcHTTPClient stops attempts to connect to unavailable address. Here is an application log:
Code:
Connect clicked
ConnectFail
Reconnect
ConnectFail
Reconnect
Disconnect 2 clicked     <<=====     I pressed "Disconnect 2" button
ConnectFail     <<=====     this event triggered right after "Disconnect 2" button pressing
<no more events>

2.2. I press "Disconnect 2" button after ConnectFail trigger. In this case RtcHTTPClient tries one more reconnect and then finished. Here is an application log:
Code:
Connect clicked
ConnectFail
Reconnect
ConnectFail
Disconnect 2 clicked     <<=====     I pressed "Disconnect 2" button
Reconnect     <<=====     this event triggered after real RtcHTTPClient.Reconnect.Wait timeout
ConnectFail
<no more events>

I think case 1 isn't intuitively clear behavior, because RtcHTTPClient should stops all reconnect attempts after manual Disconnect call. And case 2.2 is a bug, because in real applications I call Dicsonnect method after ConnectFail event trigger, but RtcHTTPClient tries one more reconnect.

Or RtcHTTPClient has alternative method for disconnecting? Though, in really, in this case we talk not about disconnecting (because RtcHTTPClient.isConnected is False), but about an operation stop.  :)


Title: Re: Problem with Disconnect method
Post by: D.Tkalcec (RTC) on February 20, 2010, 11:58:07 AM
That is what I call perfect debugging :)

Thank you very much for reporting this bug, I was able to reproduce it using your sample project and found where the problems were. I am testing my bugfixes now and will be releasing an update shortly.

Best Regards,
Danijel Tkalcec


Title: Re: Problem with Disconnect method
Post by: D.Tkalcec (RTC) on February 20, 2010, 01:14:43 PM
I have fixed the reconnect and disconnect bugs now, please download the RealThinClient SDK 3.56 (just uploaded to RTC SDK PRO Downloads area) and let me know if it is working now as it should.

Here is the output I am getting now, using the RealThinClient SDK 3.56 and an updated test project which adds a time-stamp to the output (to make it easier to see when the events are triggering) ...

Code:
12:02:48 > Connect clicked
12:03:09 > ConnectFail
12:03:19 > Reconnect
12:03:41 > ConnectFail
12:03:51 > Reconnect
12:04:12 > ConnectFail
12:04:22 > Reconnect
12:04:23 > Disconnect 1 clicked

<no more events>

12:06:03 > Connect clicked
12:06:04 > Disconnect 1 clicked

<no more events>

12:08:02 > Connect clicked
12:08:23 > ConnectFail
12:08:24 > Disconnect 1 clicked

<no more events>

12:10:04 > Connect clicked
12:10:25 > ConnectFail
12:10:35 > Reconnect
12:10:36 > Disconnect 1 clicked

<no more events>

12:13:03 > Connect clicked
12:13:24 > ConnectFail
12:13:34 > Reconnect
12:13:55 > ConnectFail
12:14:05 > Reconnect
12:14:10 > Disconnect 2 clicked  <=  now reconnect will also be disabled!

<no more events>

12:16:09 > Connect clicked
12:16:30 > ConnectFail

<no more events>

12:17:52 > Connect clicked
12:17:53 > Connect clicked
12:17:54 > Connect clicked
12:17:55 > Connect clicked
12:17:56 > Connect clicked
12:18:13 > ConnectFail

<no more events>

12:19:07 > Connect clicked
12:19:07 > Disconnect 1 clicked

<no more events>

Btw ...

When using the TRtcHttpClient component with MultiThreaded=TRUE, all events on the TRtcHttpClient component will be executed from background threads, so you should always check if "Sender.inMainThread" and use the appropriate "Sender.Sync" method to synchronize your events with the Main Thread (call it synchronized) if you are accessing the GUI (visual components).

I am saying this because in your example, you have used the TRtcHttpClient component with MultiThreaded=TRUE and were using the Memo component to LOG events of the TRtcHttpClient component, but did not check if your event is called from the Main Thread (Sender.inMainThread) and did not use the Sync method to synchronize your code with the Main Thread.

If you have code which is accessing the GUI from events triggered by the TRtcHttpClient or TRtcHttpServer component with MultiThreaded=TRUE, if you do not make sure that your code is executed from the Main Thread (by checking if "Sender.inMainThread" and using "Sender.Sync" to synchronize the event if it is NOT being executed from the Main Thread), your application would very likely start generating Access Violations or simply stop working if your event code running from the background thread would try to access the same visual components which are being accessed from the Main Thread (for example, the WM_PAINT message could arrive from Windows which would signal your visual component to repaint).

Anyway ...

I have also extended your test app to use "Sender.inMainThread" and "Sender.Sync" from TRtcHttpClient's events to make sure the Memo component is only being accessed from the main thread, and have added a time-stamp to each log line. You can either use your original test project to test the new RTC SDK version, or download my updated version, here:
http://www.realthinclient.com/debug/TestDisconnect.zip

Best Regards,
Danijel Tkalcec


Title: Re: Problem with Disconnect method
Post by: D.Tkalcec (RTC) on February 21, 2010, 09:52:11 AM
As a small "thank you" for reporting this bug and providing a clear example for reproducing it, I have extended your professional Bronze RealThinClient SDK subscription for 1 full year.

Best Regards,
Danijel Tkalcec


Title: Re: Problem with Disconnect method
Post by: Director on February 21, 2010, 06:12:26 PM
Well... :)  Thank you for fast fix and, of course, for extending my subscription  ;)

One more common question.
How correctly to make client disconnect? :)
1. when RtcHttpClient.isConnected=False I should call only Disconnect method
and
2. when RtcHttpClient.isConnected=True I should use this method (http://www.realthinclient.com/sdkarchive/index9929.html)
is it right?

how it looks in Delphi code:
Quote
procedure DisconnectClient(Client: TRtcHttpClient; IsLastClient, ProcessMessages: Boolean);
 begin
  if Client.isConnected
   then   Client.SkipRequests;
  Client.Disconnect;

  if IsLastClient
   then   while Client.TotalClientConnectionCount>0
           do   begin
                 if ProcessMessages
                  then   Application.ProcessMessages;
                 Sleep(10)
                end
 end;

P.S. MultiThreaded=True was my bug  ::)


Title: Re: Problem with Disconnect method
Post by: Director on February 21, 2010, 06:28:02 PM
1. when RtcHttpClient.isConnected=False I should call only Disconnect method
In an ideal world, I think, I should check for IsConnecting property and, if True, call Disconnect and if False - do nothing. But there is no property IsConnecting (btw, property IsClosing exists)))


Title: Re: Problem with Disconnect method
Post by: D.Tkalcec (RTC) on February 21, 2010, 07:33:50 PM
If you expect your connection should either be connected or connecting, you should simply call Disconnect without checking the current connection state. If you think you have requests pending, which you want to have removed from the request queue, use the SkipRequests or CancelRequests method (depending on the effect you want to achieve).

Also, if you need to be connected and you are not using AutoConnect=TRUE, you should simply call Connect and either expect the connection was already open before you have called Connect, or implement the "OnConectError/Fail/Lost" and "OnDisconnect" event to get notified about connection state changes - like you have done in your test project.

Calling Connect and Disconnect regardless of the current connection state will have NO negative effects, because the method checks the current state of the connection (in the background thread, where the component is used when MultiThreaded is TRUE) before deciding what to do. It is also the best way to use the components in MultiThreaded mode, since a state of a connection can change in a background thread while you are calling Connect or Disconnect, so that checking the state of a connection before calling either method will potentially do you more bad than good.

What you should keep in mind is that the RealThinClient SDK is event-driven and you should always use events to be informed about component state changes. Some states are provided in form of properties, but are there only to make some simple things possible without writing any events. But if you want your code to be thread-safe and work reliably in MultiThreaded mode, implement the required events.

Best Regards,
Danijel Tkalcec


Title: Re: Problem with Disconnect method
Post by: D.Tkalcec (RTC) on February 22, 2010, 12:52:25 AM
On a 2nd thought, having the "isConnecting" method on a client connection component is a good idea, so ... I've just released an update for the RTC SDK (3.58) which adds a public "isConnecting" method to the TRtcClient component, which means it is also available on the TRtcDataClient, TRtcHttpClient and TRtcMessageClient components.

I've also used this occasion to update the WaitForCompletion method to use the connection status and stop waiting if the connection is not going to be re-established even though requests are waiting in the request queue.

Best Regards,
Danijel Tkalcec