Forum > General

Moving from TThread.Synchronize to TThread.Queue

(1/9) > >>

cpicanco:
TThread.Synchronize is blocking, TThread.Queue is not (it returns immediately).

Ok.

If you need to send some data to the main thread, you can do something like:


--- Code: Pascal  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---// TThread classprivate  FData : TStringList; procedure SendData;begin  // do something with a copy of FDataend; // execute methodbegin  while not Terminated do  begin    FData := ReceiveData; // ReceiveData will block until some data is received     Synchronize(@SendData); // will block until finnished, so you may miss some data    // Queue(@SendData); // would return immediatelly, promptly to receive more data  end;end; 
Assuming that Queue would optimize data receivement, a problem you may face is that you must copy FData somehow to avoid overrides.

QUESTION

How to make such a copy???

sam707:
in both case (synchronise and queue)
ReceiveData is executed in your thread while SendData is Executed in main thread

If Queue used ===>
I suggest you to suspend your thread in your SendData method, to ensure that the data is not changed by an inthread concurrent ReceiveData. results are unpredicable, even crashes! (sending data while they are modified = BANG)

Either suspend, or use critical sections... see TCriticalSection for an easy way, TRTLCriticalSection record for a manually Lock control

procedure SendData;
begin
  suspended:=True;
  // do something directly with  FData
  suspended:=False;
end;

sam707:
anyway, in such case, synchronize is better, ensuring the thread do not read new arriving data, before they have been sent

the "suspended:=True" is a plaeholder trick that is not meant to always work if your CPU is very very fast and data has changed before you suspended the thread.

molly:
Perhaps i'm daft, but can't you allocate the buffer in receive() and free again in send() so that you don't have to use the exact same buffer ?

Your initial approach to copy the buffer would take the same amount of time anyway (minus the time spend on copying the buffer) so better do it at a more appropriate location ?

Mr.Madguy:

--- Quote from: cpicanco on September 15, 2017, 02:01:30 am ---How to make such a copy???

--- End quote ---
Synchronize kills all the purpose of having thread: you don't do two things at the same time - you do them one after another.

There is solution, that has been known since first computers, where this solution was used to, for example, reading keys from keyboard. Solution is simple - use buffer.

--- Code: Pascal  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---// TThread classprivate  FBuffer:TThreadededQueue<TStringList>;//Simple example - it's not that hard to construct such container by yourself procedure TMyThread.Execute;begin  while not Terminated do  begin    //Warning! If main thread hangs or can't process data fast enough - buffer may start inflating and eating your memory.    //You should monitor this situation! Buffer size should be limited for example.    FBuffer.PushItem(ReceiveData);  end;end; function TMyThread.GetData:TStringList;begin  Result := FBuffer.PopItem;//Don't forget to set PopTimeout!!!end; //Main thread  var Data:TStringList;begin  ...  Data := MyThread.GetData;  if Assigned(Data) then...  ...end; 

Navigation

[0] Message Index

[#] Next page

Go to full version