RTC Forums
November 24, 2024, 02:07:28 AM *
Welcome, Guest. Please login or register.

Login with username, password and session length
 
   Home   Help Login Register  
Pages: [1]
  Print  
Author Topic: returning data from a thread  (Read 7915 times)
jorgen
RTC Expired
*
Posts: 20


« on: March 18, 2016, 02:19:47 PM »

We currently use
TRtcDataProvider
to get data fra a database


I want to make this non blocking, calling the query in a thread.

The thread works, but it does not return any data


onDataReceived on the TRtcDataProvider

procedure TContendo_Actions.fn_DATASET(Sender: TRtcConnection);
begin
GetDataset(TRtcDataServer(Sender), Params);
end;

in
GetDataset
I create a thread:


procedure TDBThread.WriteProcessedData;
begin
DataServer.WriteProcessedData (AString, true);
end;

procedure TDBThread.Execute;
begin
  Query.Open;
  sleep(10000);
  AString := TServer_Utils.JSONFromDataset(ViewDataset.Query);
  Synchronize(WriteProcessedData);
end;



What is the best approach implementing this?



I read something about
PrepareDelayedCall
but that uses TRtcFunction and I use TRtcDataProvider




regards
Jørgen
Logged
D.Tkalcec (RTC)
Administrator
*****
Posts: 1881


« Reply #1 on: March 18, 2016, 03:25:01 PM »

Why would you want to create a new thread manually for processing your data, then wait for that thread to finish in the Main Thread, if simply setting the "MultiThreaded" property on the TRtcHttpServer component to TRUE will make all your code running from a background thread?

Best Regards,
Danijel Tkalcec
Logged
jorgen
RTC Expired
*
Posts: 20


« Reply #2 on: March 18, 2016, 05:41:49 PM »

I have now set MultiThreaded = true

It seems to work, I use a connection pool for Firedac queries.

Should the server now be multi threaded? 

Anything else I must do to support simultaneously users?


Jørgen
Logged
D.Tkalcec (RTC)
Administrator
*****
Posts: 1881


« Reply #3 on: March 20, 2016, 11:06:11 AM »

By setting the MultiThreaded property on the TRtcHttpServer component to TRUE, your Server will be Multi-Threaded, using the RTC thread pool. All events triggered by the TRtcHttpServer component, as well as any other RTC components linked to that component, will be executed from background threads (fully multi-threaded).

In a nutshell, when your Server is running in Multi-Threaded mode, RTC will be using a pool of Threads to execute all RTC code as well as all your code written inside RTC events from background threads. The number of threads in use will depend on the number of active Client connections and RTC Thread Pool parameters - defined through global variables in the rtcThrPool unit.

When using RTC components in Multi-Threaded mode, it is your responsibility to make sure that your code (everything inside RTC events) is thread-safe. Basically, the same rules apply here as when creating Threads manually and writing code to be executed inside background threads, with the only difference that you can use the "Sender.inMainThread" method to check if the event is being executed from the Main Thread and using the "Sender.Sync" method to call any RTC event (synchronized) from the Main Thread.

Best Regards,
Danijel Tkalcec
Logged
jorgen
RTC Expired
*
Posts: 20


« Reply #4 on: March 22, 2016, 10:46:18 AM »

Hello

If I do this on all events:

procedure TContendo_Actions.fn_DATASET(Sender: TRtcConnection);
begin

  if not Sender.inMainThread then
  begin
    Sender.Sync(fn_DATASET);
  end
else
begin
//DO EVERYTHING
end;
end;


will everything be executed in main thread?

It would have been nice if so. Then I can take the event on by one to check if everything is thread save and focus on the most critical parts.
Logged
D.Tkalcec (RTC)
Administrator
*****
Posts: 1881


« Reply #5 on: March 22, 2016, 12:20:22 PM »

Yes, this construct will make sure that "// DO EVERYTHING" is execute from the Main Thread.

But ... synchronizing your code with the Main Thread in a Multi-Threaded Application is ONLY required when your code has to access the GUI (Graphical User Interface, like visual components on a Form). If your code does NOT require access to any GUI elements (for example, when accessing a Database through DataSets which are NOT linked to any visual controls on any Form), you can either use a sepatate set of components for each thread (for example, by writing a Datbase Connection Pool), or use a critical section (check "TCriticalSection" class in the "SysUtils" unit) to secure code sections which should NOT be executed from more than one thread at a time.

Best Regards,
Danijel Tkalcec
Logged
jorgen
RTC Expired
*
Posts: 20


« Reply #6 on: March 22, 2016, 12:27:49 PM »

Thanks

Only reason to do this was to be able to take one part first to make sure that it works.

I do everything you have suggested, but I have to make sure that everything works and that is easier if to check if I can take one event first.


Jørgen
Logged
D.Tkalcec (RTC)
Administrator
*****
Posts: 1881


« Reply #7 on: March 22, 2016, 12:36:55 PM »

Ok. Should you have any other questions, feel free to ask.

Best Regards,
Danijel Tkalcec
Logged
jorgen
RTC Expired
*
Posts: 20


« Reply #8 on: March 29, 2016, 10:52:14 PM »

Close, but one more problem



I can  not get the sessions to work with MultiThreaded=true
It does not always find the session.


do something like this:

procedure TContendo_Actions.fn_DATASET(Sender: TRtcConnection);
begin

  with TRtcDataServer(Sender) do
    begin
  Params := Request.Query['params'];

  if  FindSession(JSession.Value) then
      Result := TRUE;

Session.AsInteger['elementid']

end;


Creeate the session like this in another request, currently in the mainthread and is allways finnished befor the other request is used.
  with TRtcDataServer(Sender) do
   OpenSession;



Do I do something wrong?

The request fn_DATASET is executed async on client so session object must be thread safe.


Jørgen
Logged
jorgen
RTC Expired
*
Posts: 20


« Reply #9 on: March 30, 2016, 08:35:47 AM »

Must I do something like this?

http://www.realthinclient.com/sf/index.php?topic=729.0
Logged
D.Tkalcec (RTC)
Administrator
*****
Posts: 1881


« Reply #10 on: March 30, 2016, 10:03:00 AM »

In a nuthell ...

If a Session exists, the FindSession method will return TRUE and LOCK that Session for exclusive use by the connection component calling the FindSession method. Any other calls to FindSession will return FALSE, for as long as the Session remains locked.

The Session will be unlocked automatically when a request/response cycle of the connection component locking the Session has finished, but you can also unlock the Session manually by using the UnLockSession method.

This "exclusive access" mechanism for Sessions is required to ensure that a Session can ONLY be used from one thread at a time. Using the same Session from multiple connections is NOT recommended, since there is always a chance that more than one connection will try to obtain access to the same Session.

Check the other Topic for a more detailed explanation.

Best Regards,
Danijel Tkalcec
Logged
jorgen
RTC Expired
*
Posts: 20


« Reply #11 on: March 30, 2016, 12:52:26 PM »

Hello
Thanks

Now it works  (probably)

calling
UnLockSession
was very important, if not, the session could be locked for a long time


Jørgen

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.029 seconds with 17 queries.