RTC Forums
November 23, 2024, 07:07:19 PM *
Welcome, Guest. Please login or register.

Login with username, password and session length
 
   Home   Help Login Register  
Pages: [1]
  Print  
Author Topic: Proper way to update components in Main Thread of Client when Mutithreaded = T  (Read 6117 times)
wbroyles
RTC Expired
*
Posts: 21


« on: September 15, 2017, 02:00:01 PM »

Do you have a example of updating the main thread using Sender.Sync.
I want to pass a string to a memo component, label,  or message box.

Thanks

Wade
 
Logged
D.Tkalcec (RTC)
Administrator
*****
Posts: 1881


« Reply #1 on: September 15, 2017, 02:24:04 PM »

Using RTC SDK v8 and later, you can call Sender.Sync() at the beginning of any RTC event (and provide the name of the event as the 1st parameter, plus any other parameters required by the event) to synchronize that event with the Main Thread. The Sync() method returns TRUE if the event was called synchronized, or FALSE if you are already in the Main Thread or if the Sync method is called from anywhere else than a Thread created by RTC.

For example ...

procedure TMyModule.MyEventToBeSynchronized(Sender:TRtcConnection [, <OptionalParameters>] );
  begin
  if Sender.Sync( MyEventToBeSynchronized [, <OptionalParameters>] ) then Exit;
  // ... from here on, you are in the Main Thread and can access components of your GUI ...

There are overloaded versions of the Sync() method for every type of RTC event available. For events where you only get the Sender:TRtcConnection parameter, the Sync() method only requires the name of the event, while events which expect more parameters need to be passed on these parameters as well. By using the Sync method this way (code example above), you can rest assured that the rest of your code inside that event (after the "Sync line") will be executed from the Main Thread.

IMPORTANT! If you are calling Sync from the method which is being synchronized, you HAVE TO call EXIT if Sync returns TRUE (see code above), or you would end up executing the same code twice (once from the Main Thread and then again from the background thread, once Sync returns).

If you are still using one of the older RTC SDK versions, where the Sync method did NOT return a result and was always calling the event synchronized, you can use the following code instead, which does the same as the above, but works with new and old RTC SDK versions ...

procedure TMyModule.MyEventToBeSynchronized(Sender:TRtcConnection [, <OptionalParameters>] );
  begin
  if NOT Sender.InMainThread then
    begin
    Sender.Sync( MyEventToBeSynchronized [, <OptionalParameters>] );
    Exit;
    end;
  // ... from here on, you are in the Main Thread and can access components of your GUI ...

Best Regards,
Danijel Tkalcec
Logged
wbroyles
RTC Expired
*
Posts: 21


« Reply #2 on: September 15, 2017, 02:43:19 PM »


This does not work. It does not like the passing of a string.

procedure TdmMain.SafeMessage(Sender: TRtcConnection; pMessage: TObject);
begin

  if Sender.Sync(SafeMessage, pMessage) then
    Exit;

  frmSyncLogin.lLog.Text := String(pMessage);

end;

procedure TdmMain.rtcResult1RequestAborted(Sender: TRtcConnection; Data, Result: TRtcValue);
var
  msg: String;
begin
  msg := 'Request Aborted';
  Sender.Sync(SafeMessage, msg);

end;
Logged
D.Tkalcec (RTC)
Administrator
*****
Posts: 1881


« Reply #3 on: September 15, 2017, 03:12:58 PM »

Instead of writing a separate method which you would be passing your own parameters, you can do everything you need to do from the Main Thread inside the same event/method that is being called by RTC, as long as you call the Sync() method as the 1st line of that event (as explained in my previous reply). In other words, following your example from above, you would do it like this ...

procedure TdmMain.rtcResult1RequestAborted(Sender: TRtcConnection; Data, Result: TRtcValue);
  begin
  if Sender.Sync(rtcResult1RequestAborted, Data, Result) then Exit;
  // ... do everything else below, you are now in the Main Thread ...
  frmSyncLogin.lLog.Text := 'Request Aborted';
  end;

As an alternative, in case you WANT to have a separate method for updating the GUI, while everything else runs in the background thread inside the "original" event called by RTC, you can do it like this ...

procedure TdmMain.My_GUI_Event(Sender: TRtcConnection; Data, Result: TRtcValue);
  begin
  if Sender.Sync(My_GUI_Event, Data, Result) then Exit;
  // ... the rest of this event will be executed from the Main Thread ...
  frmSyncLogin.lLog.Text := 'Request Aborted';
  end;
procedure TdmMain.rtcResult1RequestAborted(Sender: TRtcConnection; Data, Result: TRtcValue);
  begin
  // ... anything you want to do from the background thread before accessing the GUI comes here ...
  My_GUI_Event(Sender, Data, Result); // call your "GUI" method
  // ... anything else you want to do from the background thread comes here ...
  end;

Best Regards,
Danijel Tkalcec
Logged
wbroyles
RTC Expired
*
Posts: 21


« Reply #4 on: September 15, 2017, 04:19:56 PM »

Your missing the point. I want to use my own parameters.

Wade
Logged
wbroyles
RTC Expired
*
Posts: 21


« Reply #5 on: September 15, 2017, 04:33:58 PM »

  This seems to work.

  v := TRtcValue.Create();
  v.asString := 'Results Returned';
  SafeMessage(Sender, Data, v);
  v.Free;
Logged
D.Tkalcec (RTC)
Administrator
*****
Posts: 1881


« Reply #6 on: September 15, 2017, 05:20:24 PM »

Yep, that should work.

And if you ONLY wanted to pass a single TRtcValue object to hold your custom parameter(s), you could do it like this ...

procedure TdmMain.MySafeMessage(Sender: TRtcConnection; Data: TRtcValue);
  begin
  if Sender.Sync(MySafeMessage, Data) then Exit;
  // ... the rest of this event will be executed from the Main Thread ...
  frmSyncLogin.lLog.Text := Data.asString;
  end;

procedure TdmMain.rtcResult1RequestAborted(Sender: TRtcConnection);
  var v:TRtcValue;
  begin
  v:=TRtcValue.Create; // create object to hold the parameters
  v.asString:='Request Aborted'; // prepare parameter(s)
  MySafeMessage(Sender, v);
  v.Free; // free the object previously holding all parameters
  end;

PS. Here is the complete list of all event types currently supported by the Sync method ...

  procedure(  Sender:TRtcConnection  ) of object;

  procedure(  Sender:TRtcConnection;
                   Obj:TObject  ) of object;

  procedure(  Sender:TRtcConnection;
                   E:Exception  ) of object;

  procedure(  Sender:TRtcConnection;
                   Data:TRtcValue  ) of object;

  procedure(  Sender:TRtcConnection;
                   Obj:TObject;
                   Data:TRtcValue  ) of object;
 
  procedure(  Sender:TRtcConnection;
                   Data:TRtcValue;
                   Result:TRtcValue  ) of object;
 
  procedure(  Sender:TRtcConnection;
                   Data:TRtcValue;
                   Result:TRtcValue;
                   E:Exception  ) of object;
 
  procedure(  Sender:TRtcConnection;
                   Param:TRtcFunctionInfo;
                   Result:TRtcValue  ) of object;
 
  procedure(  Sender:TRtcConnection;
                   Param:TRtcFunctionInfo;
                   Result:TRtcValue;
                   E:Exception;
                   var Handled:boolean  ) of object;
 
  procedure(  Sender:TRtcConnection;
                   Param:TRtcObjectCall  ) of object;
 
Best Regards,
Danijel Tkalcec
Logged
wbroyles
RTC Expired
*
Posts: 21


« Reply #7 on: September 15, 2017, 06:23:35 PM »

Thanks for your help!
Logged
Pages: [1]
  Print  
 
Jump to:  

Powered by MySQL Powered by PHP Powered by SMF 1.1.21 | SMF © 2015, Simple Machines Valid XHTML 1.0! Valid CSS!
Page created in 0.05 seconds with 17 queries.