I need a TCP port component that can work as a non-blocking port for receiving data. THe data arrival should trigger an event where I can read the data.
So if I use a thread to read data from the socket, how do I signal to the main application that data are arriving using an event? Is there some resource available as a guide?
Mailing lists / lazarus / 2015-10
How does one add an event to a blocking system?
15 messages · 5 people · –
- MMichael Schnell 6
- MMark Morgan Lloyd 5
- SSven Barth 2
- BBo Berglund 1
- Lleledumbo 1
Reply by email Subscribe to this list Your subscription
Read-only archive. Use j and k to move between messages.
Bo Berglund wroteSo if I use a thread to read data from the socket, how do I signal to the main application that data are arriving using an event?
TThread.Synchronize(), TThread.Queue()
In an "Application" (other than in a "Program" you also can use "Application.QueueAsyncCall()".
You supposedly want to transfer Data to the main thread. Here IMHO it's a nice idea to use Finalizers.
-Michael
I need a TCP port component that can work as a non-blocking port for receiving data. THe…
So if I use a thread to read data from the socket, how do I signal to
the main application that data are arriving using an event?
Exactly, using an event:
http://www.freepascal.org/docs-html/fcl/syncobjs/tevent.html Here's an example of how to use:
RoundRobinExample.zip
<http://free-pascal-lazarus.989080.n3.nabble.com/file/n4044829/RoundRobinExample.zip>
TThread.Synchronize(), TThread.Queue() In an "Application" (other than in a "Program" you…
Michael Schnell wroteOn 10/21/2015 01:44 PM, Bo Berglund wrote: > So if I use a thread to read data from the socket, how do I signal to > the main application that data are arriving using an event? TThread.Synchronize(), TThread.Queue()
Please remind us what a non-LCL program has to call to make sure that stuff is dequeued.
Show quoted text 5 lines
Mark Morgan Lloyd wroteTThread.Synchronize(), TThread.Queue() Please remind us what a non-LCL program has to call to make sure that stuff is dequeued.
CheckSynchronize()
-Michael
Michael Schnell wroteCheckSynchronize()
Unfortunately there is no decent documentation on CheckSynchronize().
So in very short (and just hopefully correct):
CheckSynchronize() needs to be called by the main thread (in fact a threat becomes the main thread _because_ it calls CheckSynchronize().
The Events thrown by other Threads via TThread.Synchronize and TThread.Queue are executed as sub-procedures of CheckSynchronize() and hence they are executed in the main thread and they are executed in the order they have been queued by other threads.
It is a very bad idea to do a closed loop such as
while (TRUE) CheckSynchronize();As this will use 100 % CPU time and hence will reduce the performance of all other threads (and every application that is running on the processor).
That is why CheckSynchronize() provides using the parameter "Timeout", that defines how long to wait until returning in case no event is queued. (0 or no parameter => return immediately)
AFAIR if an Event is in the queue same is executed and CheckSynchronize(I) returns without checking if more Events are queued.
AFAIK the return parameter of CheckSynchronize() does not give any decent result and needs to be ignored.
-Michael
CheckSynchronize() -Michael
Michael Schnell wrote 7 lines
Thanks, it's one of those things I can never remember.
Mark Morgan Lloyd wroteThanks, it's one of those things I can never remember.
Because it is an fpc rtl thingy and not really meant to be used by Lazarus users ;-) .
-Michael
Unfortunately there is no decent documentation on CheckSynchronize(). So in very short…
Michael Schnell wrote 31 lines
Seems reasonable. I think I've used it in one place, which is a console program which spends most of its time waiting for keyboard input but also has
procedure MainThreadYield;
begin
Assert(InterlockedExchange(mainThreadYieldEntryCounter, 1) = 0,
'MainThreadYield reentered');
{$ifndef LCL }
CheckSynchronize;
{$endif LCL }
Assert(InterlockedExchange(mainThreadYieldEntryCounter, 0) = 1,
'MainThreadYield reexited')
end { MainThreadYield } ;I don't know whether I've overlooked anything significant there, but it appears robust and activity triggered by around half a dozen background threads appears as expected.
Mark Morgan Lloyd wrote 5 lines
Of course it's robust.
But check the CPU usage. It it's 100% all threads get just time slices- If it's just one other thread, same will never get more than 50 %.
If it's not 100% the system is waiting somewhere else in a sleep, a blocking read or similar.
-Michael
Unfortunately there is no decent documentation on CheckSynchronize(). So in very short…
"Michael Schnell" wroteCheckSynchronize() needs to be called by the main thread (in fact a
threat becomes the main thread _because_ it calls CheckSynchronize().
The part in parenthesis is wrong. CheckSynchronize checks for MainThreadID which is determined independently of CheckSynchronize.
The Events thrown by other Threads via TThread.Synchronize and
TThread.Queue are executed as sub-procedures of CheckSynchronize() and hence they are executed in the main thread and they are executed in the order they have been queued by other threads.
Better usage of terms: Exceptions are thrown (or raised), events are signaled.
AFAIR if an Event is in the queue same is executed and
CheckSynchronize(I) returns without checking if more Events are queued.
CheckSynchronize completely cwalks the lost before it returns.
AFAIK the return parameter of CheckSynchronize() does not give any decent
result and needs to be ignored.
That is indeed always "false" right now. I should check sometime what it is supposed to return... Probably whether at least one event got executed :/
Regards,
Sven
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.lazarus.freepascal.org/pipermail/lazarus/attachments/20151021/2046dba6/attachment.html>
Of course it's robust. But check the CPU usage. It it's 100% all threads get just time…
Michael Schnell wrote 7 lines
But my use of it might not have been.
Show quoted text 5 lines
CPU usage depends on what the hardware I'm emulating is doing :-)
threat becomes the main thread _because_ it calls CheckSynchronize(). The part in…
Sven Barth wroteCheckSynchronize checks for MainThreadID which is determined independently of CheckSynchronize.
I see. I suppose the would-be MainThread is just the thread that is used to start the application. That does make sense. For the internal logic of the Lazarus application the fact that it calls CheckSynchronize() is what makes the difference.
Better usage of terms: Exceptions are thrown (or raised), events are signaled.
You are right. "thrown" is not a good wording for Events. I mostly read "fired" on that behalf.
CheckSynchronize completely walks the lost before it returns.
Thanks a lot for the correction. This is very important to me (see below).
Show quoted text 7 lines
Maybe the original idea was to have CheckSynchronize execute only one Event and return TRUE if more events up are to be handled.
With this (not existing) design, I would need to do something like:
procedure TmyApplication.ProcessMessages;
begin
while CheckSynchronize() do (*nothing*) ;
end;With the current design just
procedure TmyApplication.ProcessMessages;
begin
CheckSynchronize();
end;would be OK, but the code above would work, as well and maybe should be preferred for possible future extension.
-Michael
Michael Schnell wrote 6 lines
"Signalled" is not a good choice IMO, because of unix-style signals and their handlers (e.g. sending a HUP signal to a process, to get it to re-read its configuration).
"Triggered" can have problems if a database is being used.
"Fired" seems like a fairly good choice, since it also implies immediacy.
Am 22.10.2015 10:21 schrieb "Mark Morgan Lloyd" <
Show quoted text 8 lines
signaled.
> > You are right. "thrown" is not a good wording for Events. I mostly read
"fired" on that behalf.
"Signalled" is not a good choice IMO, because of unix-style signals and
their handlers (e.g. sending a HUP signal to a process, to get it to re-read its configuration).
"Triggered" can have problems if a database is being used. "Fired" seems like a fairly good choice, since it also implies immediacy.
Yes, there is a bit of ambiguity with "signaled" and "fired" indeed seems best :)
Regards,
Sven
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.lazarus.freepascal.org/pipermail/lazarus/attachments/20151022/4f4ea5fe/attachment.html>
