Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Threads -- ACP IO -- Alertable main thread -- MessageBox

30 views
Skip to first unread message

valentin tihomirov

unread,
Aug 30, 2004, 4:24:43 PM8/30/04
to
Hello, I've presented the idea of alertable main thread in the
delphi.language.win32 newsgroup sometime ago but is did not find any
appreciation. Recently, I have been inspired by a new idea.


[1]
When a typical programmer needs to spawin a thread? In my experiance, almost
all of these lengthy tasks are IO operations. Your user clicks a button, you
should send a message over the Internet, for instance, or retreive some data
from IO device/database. You spawn a thread just to wait until lengthly IO
is complete and send result to the main thread for rendering it on a user
form. In most cases the inter thread communication (ITC) is simple but for a
minimal framework you should provide means for sending requests to the IO
thread, receiving progress/responce notifications, provide cancelliation to
keep your application responsive. In any case, neither you nor typical
single-processor PC will benefit from hundreds of waiting threads in your
system, it is a waste of system resources and your time on developing ITC
and debugging undeterministic multi-thread program.


How could we avoid threads-related problems? The main thread must be
responsive; we cannot start an IO operation in the main thread and "hang"
the UI. Let's take a typical task (from my practice): a user controls a set
of devices via UI. Write operations can be fast or slow but we must
continously asynchronously read from the devices to enable the device data
sending at arbitrary time. Here is how we can easily accomplish by the main
thread:

procedure OnCreate; // message handler
OpenFiles();
StartReads(); // start async reading
end;

procedure OnReceiveComplete(device); // read complete APC handler
UpdateStatus();
ReadFile(device); // go on async reading
end;

procedure OnSendClick(device) // message handler
WriteFile(device)
end;

procedure OnWriteComplete(device) // APC handler
UpdateStatus();
end;

procedure OnExit(); // message handler
CancelIO();
CloseDevices();
end;

We just need to make the main thread alertable to enable Asynchronous
Prodedure Call (APC) on IO completion. In a message-driven design we are not
aware of next user's desire and get prepared for everything. Do you see, the
proposed flow with ACPs is very message-driven-like. And it is until our
event-handlers are short. But what if the sequence is longer? -- The threads
are ideal for isolating a sequence of tasks like a request-responce
sequence, for instance. The use of a separate thread wrapped by a
exception-handlers would be natural:


[2]

procedure OnPerformNegotiation
try
conn:= open(peer);
try
conn.write(req_1); // blocking
i1 := conn.read(); // blocking
conn.write(req_2); // blocking
i2 := conn.read(); // blocking
...
finally
connection.close();
end;
except
LogError(e + ' negotiating with ' + peer)
end;
end;

Breaking the flow into short APC procedures, we'll get a complex state
machine which continously looses its context (local variables, exception
marks) inspite of an easy-to-follow sequence of operations in a thread. This
argument puts me into an impasse. How can we start request1 and pump
messages while waiting for the operation completion? I felt there should be
a solution but I did not want to use any "hacks" at low level. Suddenly,
I've realized that MessageBox blocks the thread while allowing it to process
messages! I have no ideas how the MessageBox works but it would be wonderful
if we could use the same main-thread unlocking technique waiting for APC to
complete:


MessageBox('I'm blocking but message loop is not');
// once clicked OK, you resume here

// start asynch IO
conn.write(req_1); // 'I'm blocking but message loop is not

// resume here
i1 := conn.read(); // 'I'm blocking but message loop is not


So, what the respected public thinks about the ideas [1] and [2]? Is the
concept grondbreaking or it is a worth nothing garbage?


PS! The proposal does not affect "direct" use cases of threads; that is,
when a thread is used for calculations on CPU.

PS! If anybody was interested by the concept, you can play building some
demos. Delphi main thread can be made alertable very easily -- copy
forms.pas into a working directory and replace
// if Done then WaitMessage;
code line in the Application.Idle procedure to
if Done then MsgWaitForMultipleObjectsEx(0, Control {fake parameter},
INFINITE, QS_ALLINPUT, MWMO_ALERTABLE);


Remy Lebeau (TeamB)

unread,
Aug 30, 2004, 4:49:34 PM8/30/04
to

"valentin tihomirov" <valentin_NO...@abelectron.com> wrote in
message news:41338c05$1...@newsgroups.borland.com...

> I've realized that MessageBox blocks the thread while
> allowing it to process messages! I have no ideas how
> the MessageBox works

It does the same thing that the TCustomForm.ShowModal() method does - it
blocks the main message queue so it runs a second message queue internally
to keep the calling thread responsive to new messages.


Gambit


valentin tihomirov

unread,
Aug 30, 2004, 6:42:02 PM8/30/04
to
> It does the same thing that the TCustomForm.ShowModal() method does - it
> blocks the main message queue so it runs a second message queue internally
> to keep the calling thread responsive to new messages.

Thank you, I supposed that but was not sure. Does the fact has any
implications? Particultarily, can we adopt such "blocks" for waiting for
async IO completion? BTW, I did not noticed the instantiation of a second
queue in that procedure, it seems that MQ of the main thread is used. Looks
like you wanted to say "blocks the main msg LOOP".


Remy Lebeau (TeamB)

unread,
Aug 30, 2004, 6:45:12 PM8/30/04
to

"valentin tihomirov" <valentin_NO...@abelectron.com> wrote in
message news:4133...@newsgroups.borland.com...

> Does the fact has any implications?

Yes, the same ones that occur when calling Application->ProcessMessages()
manually - you don't really know which messages will actually get processed
at a time, and you may have re-entrant problems if your code is not prepared
for event handlers being re-entered while they are already running from
previous messages.


Gambit


valentin tihomirov

unread,
Aug 30, 2004, 7:09:17 PM8/30/04
to

> Yes, the same ones that occur when calling Application->ProcessMessages()
> manually - you don't really know which messages will actually get
processed
> at a time, and you may have re-entrant problems if your code is not
prepared
> for event handlers being re-entered while they are already running from
> previous messages.

Yes, reentrancy (recurrency) should always be considered. Regarding
message-processing, I typically forget to disable the buttons starting an
unique async action, recording an audio for instance. As a result, the audio
device is busy when I click "start" the second time. As you see, the
reentrancy is inherent controlling asynchronous (overlapped, concurrent)
processes. Lately, I've learnt to use modal progress forms to block user
access to the "start" buttons while request is executing.


Martin James

unread,
Aug 30, 2004, 10:22:32 PM8/30/04
to

> Hello,

Hello again, Valentin :)

I've presented the idea of alertable main thread in the
> delphi.language.win32 newsgroup sometime ago but is did not find any
> appreciation.

I'm hurt! I said it would be useful.

> Recently, I have been inspired by a new idea.
>

Oh dear....

>
> [1]
> When a typical programmer needs to spawin a thread? In my experiance,
almost
> all of these lengthy tasks are IO operations. Your user clicks a button,
you
> should send a message over the Internet, for instance, or retreive some
data
> from IO device/database. You spawn a thread just to wait until lengthly IO
> is complete and send result to the main thread for rendering it on a user
> form.

I'm not convinced that this is the case. Sure, some threads do just this,
but others handle complex protocols. Others have no main thread interaction
at all.

> In most cases the inter thread communication (ITC) is simple but for a
> minimal framework

..for threads with GUI interaction...

you should provide means for sending requests to the IO
> thread, receiving progress/responce notifications, provide cancelliation
to
> keep your application responsive.

> In any case, neither you nor typical
> single-processor PC will benefit from hundreds of waiting threads in your
> system, it is a waste of system resources and your time on developing ITC
> and debugging undeterministic multi-thread program.

I think we'll have to agree to differ on this one.

>
> How could we avoid threads-related problems?

Use VB, (sorry - couldn't resist).

>Suddenly,


> I've realized that MessageBox blocks the thread while allowing it to
process
> messages! I have no ideas how the MessageBox works but it would be
wonderful
> if we could use the same main-thread unlocking technique waiting for APC
to
> complete:

I think 'wonderful' is stretching the English language a bit :)

>
> MessageBox('I'm blocking but message loop is not');
> // once clicked OK, you resume here
>
> // start asynch IO
> conn.write(req_1); // 'I'm blocking but message loop is not
>
> // resume here
> i1 := conn.read(); // 'I'm blocking but message loop is not
>
>
>
>
> So, what the respected public thinks about the ideas [1] and [2]? Is the
> concept grondbreaking or it is a worth nothing garbage?
>

Not sure. Smells a bit off but it may be my nose that is not working
correctly.

PS! If anybody was interested by the concept, you can play building some
demos. Delphi main thread can be made alertable very easily -- copy
forms.pas into a working directory and replace
// if Done then WaitMessage;
code line in the Application.Idle procedure to
if Done then MsgWaitForMultipleObjectsEx(0, Control {fake parameter},
INFINITE, QS_ALLINPUT, MWMO_ALERTABLE);

I guess you have done this. Found any problems?

Rgds,
Martin


valentin tihomirov

unread,
Aug 31, 2004, 3:06:59 AM8/31/04
to
> I've presented the idea of alertable main thread in the
> > delphi.language.win32 newsgroup sometime ago but is did not find any
> > appreciation.
>
> I'm hurt! I said it would be useful.

.. without explanation why would you need the feature. And you was the only
one.


Martin James

unread,
Aug 31, 2004, 7:47:12 AM8/31/04
to
>
> .. without explanation why would you need the feature. And you was the
only
> one.
>

Oh, I an do that.

In clients that have a lot of main-thread interaction, especially those
where the main thread needs to write, it would be useful to be able to write
without blocking and without unnecessary copying into winsock buffers. If I
can queue up APCs with WSASend in the main thread, great.

At the moment , I have to queue the send buffers to a thread that is waiting
on the queue with an alertable WFSOE, just to allow a completion proc to be
called. This is annoying.

Rgds,
Martin

PS I added the MWFMO to 'forms' tosee what would happen. No problems yet!

Martin James

unread,
Aug 31, 2004, 8:05:28 AM8/31/04
to
Incidentally, it occurs to me that the MFFMOE could actualy wait on
something. I could add a queue of my own to Tapplication & fire a
Tapplication.'onUserObject' event or call dispatch.

Why is this not just duplicating th eWindows message queue? Because the
objects waiting on this queue would be accessible & could be removed if,
say, the forms/whatever that is to receive them is being freed.

I wonder if you can derive from Tapplication & override 'Idle', to save
modifying 'forms'?

Rgds,
Martin


Marc Rohloff [TeamB]

unread,
Sep 1, 2004, 10:56:18 PM9/1/04
to
On Mon, 30 Aug 2004 23:24:43 +0300, valentin tihomirov wrote:

> Hello,

Valentin, Please don't cross post

--
Marc Rohloff [TeamB]
marc rohloff at myrealbox dot com

Craig Stuntz [TeamB]

unread,
Sep 2, 2004, 5:06:11 PM9/2/04
to

valentin tihomirov wrote:

> > Valentin, Please don't cross post
>

> I was thinking that the post is relevalnt for vcl, win32 and general
> groups.

Cross-posting is not allowed on this server, period. Please read the
rules:

http://info.borland.com/newsgroups/guide.html

Followups set.

-Craig

--
Craig Stuntz [TeamB] . Vertex Systems Corp. . Columbus, OH
Delphi/InterBase Weblog : http://blogs.teamb.com/craigstuntz
How to ask questions the smart way:
http://www.catb.org/~esr/faqs/smart-questions.html

0 new messages