Board index » delphi » Multitasking in a delphi program

Multitasking in a delphi program

Did you try to use a timer to control the update of the desired memory
location?
E-mail me, if you need more informations.

Christian (he...@imt.unine.ch)

From: m-14...@mailbox.swipnet.se (Kurt Anneborg)
Newsgroups: comp.lang.pascal.delphi.misc
Subject: Re: Multitasking in a delphi program
Date: 1 Nov 1995 06:37:00 GMT
Organization: Kandex HB
Mime-Version: 1.0
Message-ID: <4774ic$kuk@mn5.swip.net>
References: <476dov$1o3@wombat.melbpc.org.au>

In article <476dov$...@wombat.melbpc.org.au>, bigb...@melbpc.org.au
says...

Quote

>Hello. I am writing a program in Delphi that waits for a memory
>location to be updated (by a dos device driver). Only problem is,
>while I am waiting in this loop, the rest of windows cannot run.

>Is there any way that I can only check so often, and enable the rest
>of windows to operate? Like pass on the task time?

>Please help.

Hello! I have almost the same problem to solve. I friend of mine has
a solution in the Win 3.1-corporative style, but in my case, I'm not
able to control the process to 100%. I'm patiently awaiting the
32-bits issue of Delphi, where I can implement multithreading in a
Windows 95-environment(or NT). I've done this earlier in C under OS/2
and this is the way to go. If You are in a hurry (When Delphi-32??)
and persist in your plans to use Win 3.1, please send an e-mail and
I'll try to help You.
----------------------------------------------------------------------
Kurt.Anneb...@mailbox.swipnet.se
Kandex System Development
======================================================================
 

Re:Multitasking in a delphi program


Quote
bigb...@melbpc.org.au (Brian Dodgson) wrote:
>Hello. I am writing a program in Delphi that waits for a memory
>location to be updated (by a dos device driver). Only problem is,
>while I am waiting in this loop, the rest of windows cannot run.

>Is there any way that I can only check so often, and enable the rest
>of windows to operate? Like pass on the task time?

You'll undoubtedly get lots of responses to this; it's quite simple.
Put the following line in your wait loop:

        Application.ProcessMessages;

That tells your program to process any Windows control messages in the
input queue, which results in them getting farmed out to other
programs as they should be receiving them. Welcome to the wonderful
world of cooperative multitasking.

--
Sean R. Malloy               | American Non Sequitur
    Naval Medical Center     |       Society
    San Diego, CA 92134-5000 |
mal...@cris.com              | "We may not make sense,
srmal...@snd10.med.navy.mil  |  but we do like pizza"

Re:Multitasking in a delphi program


In article <476dov$...@wombat.melbpc.org.au>, bigb...@melbpc.org.au
says...
Quote

>Hello. I am writing a program in Delphi that waits for a memory
>location to be updated (by a dos device driver). Only problem is,
>while I am waiting in this loop, the rest of windows cannot run.

>Is there any way that I can only check so often, and enable the rest
>of windows to operate? Like pass on the task time?

>Please help.

Hello! I have almost the same problem to solve. I friend of mine has
a solution in the Win 3.1-corporative style, but in my case, I'm not
able to control the process to 100%. I'm patiently awaiting the
32-bits issue of Delphi, where I can implement multithreading in a
Windows 95-environment(or NT). I've done this earlier in C under OS/2
and this is the way to go. If You are in a hurry (When Delphi-32??)
and persist in your plans to use Win 3.1, please send an e-mail and
I'll try to help You.
----------------------------------------------------------------------
Kurt.Anneb...@mailbox.swipnet.se
Kandex System Development
======================================================================

Re:Multitasking in a delphi program


Check the Help for ProcessMessages.
Place Application.ProcessMessages in your checking loop.
John.

Re:Multitasking in a delphi program


Quote
> In article <476dov$...@wombat.melbpc.org.au>, bigb...@melbpc.org.au
> says...

> >Hello. I am writing a program in Delphi that waits for a memory
> >location to be updated (by a dos device driver). Only problem is,
> >while I am waiting in this loop, the rest of windows cannot run.

> >Is there any way that I can only check so often, and enable the rest
> >of windows to operate? Like pass on the task time?

> >Please help.

In your loop to keep testing the memory location, put the command
Application.ProcessMessages.

Tom

Re:Multitasking in a delphi program


I wrote a multi-threading unit for TurboPascal 7 which works nice, but I
am having trouble converting it to windows.

Is there anything I should know about stack switching withing windows?

--
Sam Liddicott                                  
Campbell Scientific Ltd.                        
14-20 Field Street, Shepshed,                  
Leicestershire,                            Phone: +44 (0) 1509 601141
United Kingdom. LE12 9AL                   Fax:   +44 (0) 1509 601091

Re:Multitasking in a delphi program


In article 100...@csluk.demon.co.uk, Sam Liddicott <s...@csluk.demon.co.uk> writes:

Quote

>I wrote a multi-threading unit for TurboPascal 7 which works nice, but I
>am having trouble converting it to windows.

>Is there anything I should know about stack switching withing windows?

>--
>Sam Liddicott                                  
>Campbell Scientific Ltd.                        
>14-20 Field Street, Shepshed,                  
>Leicestershire,                            Phone: +44 (0) 1509 601141
>United Kingdom. LE12 9AL                   Fax:   +44 (0) 1509 601091

 Use multi-threading in Win32 of Windows 95. It commes with
 Delphi 32

 MAUS, v902...@si.hhs.nl

Re:Multitasking in a delphi program


Quote
bigb...@melbpc.org.au (Brian Dodgson) wrote:
>Hello. I am writing a program in Delphi that waits for a memory
>location to be updated (by a dos device driver). Only problem is,
>while I am waiting in this loop, the rest of windows cannot run.

Try this:

While Memory_not_ready {your function} do
    Application.ProcessMessages;

Regards
Wai Wong.

Re:Multitasking in a delphi program


Quote
On Thu, 2 Nov 1995, Sens wrote:
> In article 100...@csluk.demon.co.uk, Sam Liddicott <s...@csluk.demon.co.uk> writes:

> >I wrote a multi-threading unit for TurboPascal 7 which works nice, but I
> >am having trouble converting it to windows.

> >Is there anything I should know about stack switching withing windows?

>  Use multi-threading in Win32 of Windows 95. It commes with
>  Delphi 32

Which alas is not present.  Just a simple co-operative multi-thread would
be nice.  I think I have to alloc some mem, lock it in memory, alloc a
selector, set its status to <something> and - away..... switch stacks
when I want...

Does it have a minimu size, or does windows switch stacks every time you
call the kernal?

does this sound right?

--
Sam Liddicott                                  
Campbell Scientific Ltd.                        
14-20 Field Street, Shepshed,                  
Leicestershire,                            Phone: +44 (0) 1509 601141
United Kingdom. LE12 9AL                   Fax:   +44 (0) 1509 601091

Re:Multitasking in a delphi program


Quote
v902...@si.hhs.nl (Sens) wrote:
>In article 100...@csluk.demon.co.uk, Sam Liddicott <s...@csluk.demon.co.uk> writes:

>>I wrote a multi-threading unit for TurboPascal 7 which works nice, but I
>>am having trouble converting it to windows.

>>Is there anything I should know about stack switching withing windows?

>>--
>>Sam Liddicott                                  
>>Campbell Scientific Ltd.                        
>>14-20 Field Street, Shepshed,                  
>>Leicestershire,                            Phone: +44 (0) 1509 601141
>>United Kingdom. LE12 9AL                   Fax:   +44 (0) 1509 601091

I do it like this, hope you understand.

Unit Switcher;

{$F+,G-,S-}

Interface

Const
  StackMargin = 1024;   { Marge onder StackMark }

Type
  PStackFrame = ^RStackFrame;
  RStackFrame = Record
    BP: Word;           { Context wijst naar dit record }
    Start: Pointer;
    {Par2: Pointer;      { 2 parameters van Switch }
    Par1: Pointer;

    Return: Pointer;    { Na de return van Switch is dit het terugkeer }
    SelfPar: Pointer;   { adress van Caller }

    return2: Pointer;   { Dit is het stackframe voor Stop }
    SelfPar2: Pointer;
  End;

  PContext = ^RContext;
  RContext = Record
    Buf: Pointer;
    Size: Word;
    Len: Word;
    Stack: Word;
  End;

Var
  StackMark: Word; { Plaats op de stack waar processen hun eigen stack
hebben }
  ApplicationContext: Word;

procedure MarkStack;
function NewContext(StartAdress, TerminateAddress, SelfPtr: Pointer):
PContext;
procedure DisposeContext(C: PContext);
procedure CallProcess(C: PContext);
procedure ReturnProcess(C: PContext);

Implementation

{-----------------------------------------------------------------}
{ SWITCH - Schakelt tussen twee stacks                            }
{-----------------------------------------------------------------}
procedure SSSwitch(var SaveContext, NewContext: Pointer); assembler;
Asm
  cli                   { Liever geen interrupts }

  les bx,SaveContext    { Adres om Context op te slaan }
  mov ax,sp
  mov es:[bx],ax
  mov ax,ss
  mov es:[bx+2],ax

  les bx,NewContext     { Adres van nieuwe Context }
  les bx,es:[bx]        { Pak context pointer (var!) }
  mov ax,bx
  mov sp,ax
  mov ax,es
  mov ss,ax

  sti                   { Nu mogen ze weer }
End;

{ MarkStack word aangeroepen door de applikatie.
  Als een proces wordt aangeroepen, mag de stack niet onder de stackmark
uitkomen.}
procedure MarkStack;
Begin
  StackMark := SPTR - StackMargin;
End;

{ Schakelt van de applikatie naar een proces }
procedure CallProcess(C: PContext);
Begin
  ApplicationContext := SPtr;
  If ApplicationContext < StackMark Then
  Begin
    RunError(202);
    Exit;
  End;

Asm
  cli                   { Liever geen interrupts }
End;

  Move(C^.Buf^, Ptr(SSeg, C^.Stack)^, C^.Len);

Asm
  les bx,C;
  mov ax,RContext(ES:[BX]).Stack
  mov sp,ax

  sti                   { Nu mogen ze weer }
End;

End;

{ Save de context van een proces en ga terug naar de applicatie }
procedure ReturnProcess(C: PContext);
Begin
  C^.Stack := SPtr;              { Bewaar Stackpointer }
  C^.Len := StackMark-C^.Stack;   { Bereken gebruikte stackgrootte }
  If C^.Len > C^.Size Then        { Genoeg ruimte in de buffer }
  Begin
    FreeMem(C^.Buf, C^.Size);     { Nee, alloceer dan nieuwe buffer }
    C^.Size := C^.Len;
    GetMem(C^.Buf, C^.Size);
  End;
  Move(Ptr(SSeg,C^.Stack)^, C^.Buf^, C^.Len);      { Copieer Stack }

  Asm
    cli

    mov ax, ApplicationContext    { Pak de applikatie stack weer }
    mov sp, ax                    { Nieuwe context }

    sti
  End;
End;

function NewContext(StartAdress, TerminateAddress, SelfPtr: Pointer):
PContext;
Var
  C: PContext;
Begin
  New(C);       { Ruimte voor een nieuwe Context }
  C^.Size := 2*SizeOf(RStackFrame);
  GetMem(C^.Buf, C^.Size);
  C^.Len := SizeOf(RStackFrame);
  C^.Stack := StackMark-C^.Len;
  With PStackFrame(C^.Buf)^ Do
  Begin
    { Stack layout voor return van TPROCESS.TERMINATE }
    SelfPar2 := SelfPtr;
    Return2 := nil;     { Keert nooit terug}

    { Stack layout voor return van TPROCESS.CALLER }
    SelfPar := SelfPtr;
    Return  := TerminateAddress;

    { Stack layout voor return van SWITCH }
    {Par2  := nil;}
    Par1  := nil;
    Start := StartAdress; { Hier begint het na Switch }
    BP    := 0;
  End;
  NewContext := C;
End;

procedure DisposeContext(C: PContext);
Begin
  Freemem(C^.Buf, C^.Size);
  Dispose(C);
End;

End.
--

-----------------------------------
Arjan Lamaker
IMAG-DLO Wageningen The Netherlands
mail: e.j.j.lama...@imag.agro.nl
http://huizen.dds.nl/~lamaker/
-----------------------------------

Re:Multitasking in a delphi program


Quote
bigb...@melbpc.org.au (Brian Dodgson) wrote:
>Hello. I am writing a program in Delphi that waits for a memory
>location to be updated (by a dos device driver). Only problem is,
>while I am waiting in this loop, the rest of windows cannot run.
>Is there any way that I can only check so often, and enable the rest
>of windows to operate? Like pass on the task time?
>Please help.

You've heard that Application.ProcessMessages will let
windows have time to process other things. If that takes
care of it for you, ignore what follows.

In principle, polling a memory location is a very bad way
to wait, unless the wait time is guaranteed to be shorter
than the overhead of a context switch. The other side of
the coin is that today's processors are fast enough that it
usually doesn't matter (assuming you Application.ProcessMessages),
unless you have a _lot_ of processes doing it, and the context
switching for all those two-instruction memory pollings
is eating into time available for an active process.

Anyway, the alternative to watching for the DOS driver to
do something is to let it tell you. In windows you want a
windows message to respond to. I am pretty sure there is a
way short of a VXD to arrange for a DOS driver or TSR to call
into windows to post a message. I haven't done it myself,
but as I recall, windows broadcasts some Int 2Fh stuff to
announce its startup and shutdown, so drivers can know what
is going on. The rest involves using DPMI (DOS Protected Mode
Interface) calls to set up a call-back for the DOS driver to use,
and presumably informing the driver of it through a handshake
etc, (I admit to handwaving at this point, but I can't dig for
it right now, especially if someone has some working code to post).

Of course this presumes you are writing the DOS driver, or can
trap the events of interest, and want to get into this stuff instead
of glorying in oo abstractions far removed from gnarly platform-
dependencies. It's a no-brainer if you have a choice.

If you really want to pursue this, I think I can dig up the
references, but let's see if someone volunteers some code ;-)

Regards,
Bengt Richter

Re:Multitasking in a delphi program


In <47e8gh$...@news.accessone.com> b...@accessone.com (Bengt Richter)
writes:

Quote

>bigb...@melbpc.org.au (Brian Dodgson) wrote:

>>Hello. I am writing a program in Delphi that waits for a memory
>>location to be updated (by a dos device driver). Only problem is,
>>while I am waiting in this loop, the rest of windows cannot run.

>>Is there any way that I can only check so often, and enable the rest
>>of windows to operate? Like pass on the task time?

>>Please help.

>You've heard that Application.ProcessMessages will let
>windows have time to process other things. If that takes
>care of it for you, ignore what follows.

>In principle, polling a memory location is a very bad way
>to wait, unless the wait time is guaranteed to be shorter
>than the overhead of a context switch. The other side of
>the coin is that today's processors are fast enough that it
>usually doesn't matter (assuming you Application.ProcessMessages),
>unless you have a _lot_ of processes doing it, and the context
>switching for all those two-instruction memory pollings
>is eating into time available for an active process.

>Anyway, the alternative to watching for the DOS driver to
>do something is to let it tell you. In windows you want a
>windows message to respond to. I am pretty sure there is a
>way short of a VXD to arrange for a DOS driver or TSR to call
>into windows to post a message. I haven't done it myself,
>but as I recall, windows broadcasts some Int 2Fh stuff to
>announce its startup and shutdown, so drivers can know what
>is going on. The rest involves using DPMI (DOS Protected Mode
>Interface) calls to set up a call-back for the DOS driver to use,
>and presumably informing the driver of it through a handshake
>etc, (I admit to handwaving at this point, but I can't dig for
>it right now, especially if someone has some working code to post).

>Of course this presumes you are writing the DOS driver, or can
>trap the events of interest, and want to get into this stuff instead
>of glorying in oo abstractions far removed from gnarly platform-
>dependencies. It's a no-brainer if you have a choice.

>If you really want to pursue this, I think I can dig up the
>references, but let's see if someone volunteers some code ;-)

>Regards,
>Bengt Richter

Have seen big improvements in loop execution if not called every loop
cycle. Call Every 200 ms or depending on speed of user.
Alex P

Re:Multitasking in a delphi program


Quote
>bigb...@melbpc.org.au (Brian Dodgson) wrote:

>Hello. I am writing a program in Delphi that waits for a memory
>location to be updated (by a dos device driver). Only problem is,
>while I am waiting in this loop, the rest of windows cannot run.

>Is there any way that I can only check so often, and enable the rest
>of windows to operate? Like pass on the task time?

------------------------------------------------------------------------
A. If all your application is doing is waiting, then just put
Application.ProcessMessages in your loop. This will give other Windows
applications a chance.

B. If you want to do other things while you wait for the change, then the
simple answer is to use a tTimer (or a thread in Delphi32) to call your
processing routine when the value changes.  This is the best solution in the
sense that it is general and will not make you dependent on a particular
device driver. It may not be the most efficient.

Some comments that happen to come to mind:

Too short an interval on the timer and there is a lot of wasted execution time.
Timers are in short supply, try not to use more than one per application.

The  root of the problem is that Windows programs are essentially event
driven, not state driven. Windows is designed for events and that is what one
wants most of the time in Windows. If you were programming an embedded system
state driven programming might predominate. For state changes that do not
generate interrupts one has to poll the state variables, i.e. multitasking of
some sort.

If you can tie into an interrupt, message or call-back it will be more
efficient (usually). Most devices generate interrupts which Windows picks up.

Hope this helps ...

Re:Multitasking in a delphi program


Quote
m...@zeus.hsrc.ac.za (Malcolm Coulter) wrote:
>>bigb...@melbpc.org.au (Brian Dodgson) wrote:

>>Hello. I am writing a program in Delphi that waits for a memory
>>location to be updated (by a dos device driver). Only problem is,
>>while I am waiting in this loop, the rest of windows cannot run.

>>Is there any way that I can only check so often, and enable the rest
>>of windows to operate? Like pass on the task time?
>------------------------------------------------------------------------
>A. If all your application is doing is waiting, then just put
>Application.ProcessMessages in your loop. This will give other Windows
>applications a chance.

>B. If you want to do other things while you wait for the change, then the
>simple answer is to use a tTimer (or a thread in Delphi32) to call your
>processing routine when the value changes.  This is the best solution in the
>sense that it is general and will not make you dependent on a particular
>device driver. It may not be the most efficient.

>Some comments that happen to come to mind:

>Too short an interval on the timer and there is a lot of wasted execution time.
>Timers are in short supply, try not to use more than one per application.

>The  root of the problem is that Windows programs are essentially event
>driven, not state driven. Windows is designed for events and that is what one
>wants most of the time in Windows. If you were programming an embedded system
>state driven programming might predominate. For state changes that do not
>generate interrupts one has to poll the state variables, i.e. multitasking of
>some sort.

>If you can tie into an interrupt, message or call-back it will be more
>efficient (usually). Most devices generate interrupts which Windows picks up.

>Hope this helps ...

Perhaps you should ask Sam Liddicott for help. He has a multithreading
component, why, when you implement it, might resolve your situation.
Check out any articles with his name on and e-mail him a request...

Hope this helps

Stefan Paetow
ellipse data systems

--
////////////////////////////////////////////////////
//Remember that my e-mail address is invalid after//
//20 November 1995. Please do not forget me while //
//I'm in Internet isolation. My postal address is://
//P.O.Box 11515                                   //
//Tremloods                                       //
//0126                                            //
//Pretoria                                        //
//Republic of South Africa                        //
////////////////////////////////////////////////////

Other Threads