forget coorporative multitasking in .NET ?

  • Thread starter Thread starter Guest
  • Start date Start date
G

Guest

Hi,

After various question (here and on other places) it seems prremtive
multitasking is the way to go with .NET. But wat about coorporative
multitasking ? While this was so powerfull and easy to do in win32 ? Ok it is
still possible but it seems only with P/Invoke thing and using the old way.
But when I ask queston everyone talk to me to use threads, whil this is
normally (or was not) nececary. Even if using the non blocking things (like
for TCP), it is preemtive. It just start another (blocking) thread.

I start to like .NET because I know a little bit of it (very little bit),
but this is something I dont like. Please help me clear my mind :)
 
Wilfried said:
Hi,

After various question (here and on other places) it seems prremtive
multitasking is the way to go with .NET. But wat about coorporative
multitasking ? While this was so powerfull and easy to do in win32 ? Ok it is
still possible but it seems only with P/Invoke thing and using the old way.
But when I ask queston everyone talk to me to use threads, whil this is
normally (or was not) nececary. Even if using the non blocking things (like
for TCP), it is preemtive. It just start another (blocking) thread.

I start to like .NET because I know a little bit of it (very little bit),
but this is something I dont like. Please help me clear my mind :)

You want co-operative multitasking in your own application? Don't use
threads then. Simply write a state-machine and a scheduler, and your
application in the form of state handlers.

Frans.

--
 
Wilfried Mestdagh said:
After various question (here and on other places) it seems prremtive
multitasking is the way to go with .NET. But wat about coorporative
multitasking ? While this was so powerfull and easy to do in win32 ? Ok it is
still possible but it seems only with P/Invoke thing and using the old way.
But when I ask queston everyone talk to me to use threads, whil this is
normally (or was not) nececary. Even if using the non blocking things (like
for TCP), it is preemtive. It just start another (blocking) thread.

I start to like .NET because I know a little bit of it (very little bit),
but this is something I dont like. Please help me clear my mind :)

Using Application.DoEvents is effectively co-operative multitasking -
and something I recommend avoiding.

Using threads is tricky, but I think it's a better solution overall
than trying to keep everything straight with co-operative multitasking.
To me, co-op was basically a way of faking things until pre-emptive
multitasking was available. What do you think are the advantages of
using co-operative multitasking rather than pre-emptive?
 
Wilfried said:
Hi,

After various question (here and on other places) it seems prremtive
multitasking is the way to go with .NET. But wat about coorporative
multitasking ? While this was so powerfull and easy to do in win32 ? Ok it
is still possible but it seems only with P/Invoke thing and using the old
way. But when I ask queston everyone talk to me to use threads, whil this
is normally (or was not) nececary. Even if using the non blocking things
(like for TCP), it is preemtive. It just start another (blocking) thread.

I start to like .NET because I know a little bit of it (very little bit),
but this is something I dont like. Please help me clear my mind :)

For some reason, Microsoft in general /fears/ threads.

Anything that allows Windows to be more efficient, and keep people from
buying upgrades in the hopes of getting a faster machine, must be shunned.

That is why the 2.6 kernel blows the doors off Windos.
 
The Man With The Golden Gun said:
For some reason, Microsoft in general /fears/ threads.

What makes you think that? If MS feared threads, why would there be
threading support in .NET?
Anything that allows Windows to be more efficient, and keep people from
buying upgrades in the hopes of getting a faster machine, must be shunned.

I don't see any evidence of that whatsoever.
 
Hi Jon,
Using Application.DoEvents is effectively co-operative multitasking -
and something I recommend avoiding.

Agree to avoid it. It enters the message pump and the code can be re-entered
if it starts from the message pump. In general code has to execute as fast as
possible then it is not needed to call it.
What do you think are the advantages of
using co-operative multitasking rather than pre-emptive?

There are 2. First of all you know exacly what is executing at a given time,
for example if a code block is executing, no other is running until it ends
and the system enters the message pump.

The second comes form the first and is that you never have to worry about
synchronizing or critical sections of wait events. Bot of these reasons make
it very easy to program.

As Frans already mentioned, writing a state machine is a very easy thing to
do, in fact I find it more easy than sequentional programming. An example is
winsock in win32 API. It can be written 2 way, and that is the blocking
method which is more easy to write, but then every socket has his own thread,
the other is asynchronious where windows needs a working message pump in a
hidden window. I always have done the latter to avoid thread.

But for example winsock in NET even if using the non blocking model with the
Invoke, then it is still threaded code, and I find this is not needed. I
think threads are only needed for length operations, for example opening a
large database or parsing a long bunch of data.

rgds, Wilfried
http://www.mestdagh.biz
 
Not sure where you get this from. Cooperative (not coorporative )
multitasking was a 'feature' of 16 bit windows (Windows 3.x) NOT a Win32
based OS feature.
For backward compatibility Windows 9x support cooperative multitasking for
16 bit Windows applications through a 16 bit subsystem where all programs
run in a separate Virtual Machine, sharing the same address space the same
message queue and the same thread of execution.
32 bit programs can hardly run in a cooperative mode as they don't share the
virtual address space, their threads have a private message queue, and these
threads are scheduled by the OS scheduler.

Willy.
 
See inline ***

Willy.

Wilfried Mestdagh said:
Hi Jon,


Agree to avoid it. It enters the message pump and the code can be
re-entered
if it starts from the message pump. In general code has to execute as fast
as
possible then it is not needed to call it.


There are 2. First of all you know exacly what is executing at a given
time,
for example if a code block is executing, no other is running until it
ends
and the system enters the message pump.

*** This was true on 16 bit windows but not any longer on Win32. The OS
scheduler is the master of the game not your application code, your threads
will pre-empt when the scheduler decides to do so.
The second comes form the first and is that you never have to worry about
synchronizing or critical sections of wait events. Bot of these reasons
make
it very easy to program.

*** No it comes from the fact that your code runs on a pre-empted OS,
whatever you do in your single thread of execution you can't (easily) block
the whole system, something which was very easy to do on Windows 3.x.
As Frans already mentioned, writing a state machine is a very easy thing
to
do, in fact I find it more easy than sequentional programming. An example
is
winsock in win32 API. It can be written 2 way, and that is the blocking
method which is more easy to write, but then every socket has his own
thread,
the other is asynchronious where windows needs a working message pump in a
hidden window. I always have done the latter to avoid thread.

*** I must be missing something here, how can something be asynchronous if
you have only one single thread to run the pump and to do socket IO?
And I don't get the relation between the hidden window and a Socket.
 
Willy,

This makes me curious, I know the term multitasking as an IBM term, what was
a substitute of multiprogramming a term used by Burroughs. Multiprogramming
did mean that you did not have to keep track on the programs that where
executed, they where managed by the OS side by side. Although you could (as
far as I remember me) set with multiprogramming priorities about scheduling,
executing and virtual memory, while there where a lot of possibilities of
queuing and to synchronize the programs that used those what you can call
using programs as threads.

Mutlitasking was something (it was in the seventies) you had to set by hand
(JCL) in those days. However there was an advantage from multitasking, with
multitasking you had to tell what part of memory would be used and therefore
the memory was protected. What was impossible with a Burroughs system
(although I have never seen an error with that and was coding in BPL (a PL1
substitude) and Cobol for that computer). IBM has forever had a good
marketing team, so you know probably how important that memory protection
became.

For those days a Burroughs system was great, however probably much too
advanced for those days.

In a Burroughs system was everytime the program pushed down, when there was
a new one loaded.

Therefore I compare that Burroughs system often with W9x while as we know
NTx comes from that IBM OS although it is not anymore done by hand (JCL).

Can you maybe give me some light if my comparing is wrong in this, because I
was a long time not interested in computer OS architecture however want to
know where I am wrong in my ideas?

Cor
 
Cor said:
Willy,

This makes me curious, I know the term multitasking as an IBM term, what was
a substitute of multiprogramming a term used by Burroughs. Multiprogramming
did mean that you did not have to keep track on the programs that where
executed, they where managed by the OS side by side. Although you could (as
far as I remember me) set with multiprogramming priorities about scheduling,
executing and virtual memory, while there where a lot of possibilities of
queuing and to synchronize the programs that used those what you can call
using programs as threads.

Mutlitasking was something (it was in the seventies) you had to set by hand
(JCL) in those days. However there was an advantage from multitasking, with
multitasking you had to tell what part of memory would be used and therefore
the memory was protected. What was impossible with a Burroughs system
(although I have never seen an error with that and was coding in BPL (a PL1
substitude) and Cobol for that computer). IBM has forever had a good
marketing team, so you know probably how important that memory protection
became.

For those days a Burroughs system was great, however probably much too
advanced for those days.

In a Burroughs system was everytime the program pushed down, when there was
a new one loaded.

Therefore I compare that Burroughs system often with W9x while as we know
NTx comes from that IBM OS although it is not anymore done by hand (JCL).

Can you maybe give me some light if my comparing is wrong in this, because I
was a long time not interested in computer OS architecture however want to
know where I am wrong in my ideas?

I don't know what IBM nor JCL (?) has to do with it, but the thing is this:
on 16 bit windows (win3.xx), the scheduler worked with 16bit processes
only and basicly scheduled the processes/threads once the thread who had
the processor gave execution back to the scheduler. This is called
'co-operative' as multi-tasking was depending on the cooperation between
applications. I.e.: if an application didn't give execution back to the
scheduler, the system 'hanged' (no other threads got the CPU) unless a
non-maskable interrupt was triggered.

on 32bit windows based on the win95 kernel (win9x, winME) the scheduler
worked pre-emptively. This means that the whole system was divided in
32bit processes and the scheduler scheduled the threads of these
processes using a priority stack and some other protocols (mostly
round-robin). Each thread in the system was given a fixed amount of
time, after that, the scheduler simply took teh CPU away from the thread
and the thread was physically halted as another thread was given the
CPU. It depended on the priority/place in teh thread queue which thread
was given the CPU. This is totally different from the 16bit OS, as the
scheduler decided which thread was given the CPU, not the thread
currently running.

16bit applications were all ran in a single 32bit process. 16bit
processes on 16bit windows shared the system memory so they all had
access to eachother memory and as they were all scheduled as 1 process,
their multitasking was still depending on co-operation, as the whole
16bit process space was given the CPU, inside it it was then decided
which process got the CPU, i.e.: the last process which had the CPU.

On 32bit windows based on the NT kernel, this is not that different,
except from teh fact that 16bit processes are run inside a virtual machine.

Co-operative multi-tasking is stupid. It easily hangs the machine.
(win9x/ME also had problems with 16bit processes which stepped on its
own 16bit OS libraries (as they all shared the same memory), for example
parts of the shell were 16bit code, so a bad 16bit program could hang
the complete system, as it could overwrite parts of the OS without
having the OS stopping it because of a GPF)

Co-operative multi-tasking is also just a trick to do things 'in
parallel' without having to work with threads. The reason why some
people still want it is that they want to do things in parallel in a
synchronious way, as in pre-emptive multi-tasking it is undefined which
thread gets the cpu and when, so it requires extra code to make
asynchronous code work as planned and debugging that kind of code can be
cumbersome.

We all do have synchronous multitasking code today: simply write a
routine and call from that routine your other routines. That's
co-operative multitasking. As I wrote earlier, a state-machine can help
you with this. You can chop up a long running routine into several
states and hop between them using the state machine, which then allows
you to add states in between these 'substates' to get things done in
parallel, but in a synchronous way. Using this I wrote 13 years ago a
parallel computing system for a 120-node sparc cluster (in C) which
could schedule and dispatch jobs on all the nodes, synchronously and in
parallel without having to have a lot of threads and syncing code in place.

Frans.

--
 
Frans,

Thanks, reading this my mind did say everytime of course.

So it added to my knowledge that it was restoring from the back to the
front.
(Although there are as well new elements)

For me was IBM the first who came with that "MultiTasking" term and JCL is
Job Control Language.
http://www.okstate.edu/cis_info/cis_manual/jcl_toc.html

As far as I remember me, where there 2 terms in past, multiprogramming what
was doing more programs, processes, threads on one system. Multiprocessing
could not be used because that was doing one process on more processors.

However than came IBM with "multitasking", probably with the same reasons as
you tell it about how the words where used in the ms-Dow/Wind311
environment.

And in the oposite maybe from you about 25-30 years ago I made a system with
a seperated database layer, securitylayer, business layer and datacom (ui)
layer with threads who where working side by side using queues, and all was
done none parallel and therefore securing a high throughput.

However when I had directly searched on Google I could have found a lot of
answers, from what I don't say that your answer did not give something
extra.

http://en.wikipedia.org/wiki/Computer_multitasking#Multiprogramming

Thanks again for your explanation.

Cor
..
 
Wilfried Mestdagh said:
Agree to avoid it. It enters the message pump and the code can be re-entered
if it starts from the message pump. In general code has to execute as fast as
possible then it is not needed to call it.

So if you're doing *anything* long-running - or even potentially long-
running, like file access, you either have an unresponsive UI or you
*have* to use threads (or call Application.DoEvents).
There are 2. First of all you know exacly what is executing at a given time,
for example if a code block is executing, no other is running until it ends
and the system enters the message pump.

The second comes form the first and is that you never have to worry about
synchronizing or critical sections of wait events. Bot of these reasons make
it very easy to program.

Sure. That's fine if your code never does anything which might be long-
running at all. I find that situation is pretty rare.
As Frans already mentioned, writing a state machine is a very easy thing to
do, in fact I find it more easy than sequentional programming.

I suggest you're unusual in that respect. If I have two things which I
want to execute effectively in parallel, writing a state machine and
making sure that *all* calls are going to be non-blocking is much
harder for me than just using two threads. If the two things are highly
interdependent, it becomes trickier, but very often they're not.

State machines have their place, but I find threads great for doing two
relatively independent tasks effectively simultaneously.
An example is
winsock in win32 API. It can be written 2 way, and that is the blocking
method which is more easy to write, but then every socket has his own thread,
the other is asynchronious where windows needs a working message pump in a
hidden window. I always have done the latter to avoid thread.

In .NET you can use sockets asynchronously without having an extraneous
window, of course. It uses thread-pool threads, so you still need to
worry about threading, but you don't need to spawn new threads directly
yourself.
But for example winsock in NET even if using the non blocking model with the
Invoke, then it is still threaded code, and I find this is not needed. I
think threads are only needed for length operations, for example opening a
large database or parsing a long bunch of data.

I think I view far more operations as being potentially time-consuming
than you do. For instance, I regard pretty much any file access as
potentially time-consuming. If I'm encoding a bunch of MP3s with one
program, other programs may well have to wait a significantly long time
to get disk access, and I don't want my UI to lock up while that's
happening.

Of course, threads give you other possible improvements on multi-
processor machines, too.
 
Hi Frans,

I do have one small disagreement with your otherwise excellent description.
We all do have synchronous multitasking code today: simply write a
routine and call from that routine your other routines. That's
co-operative multitasking.

I disagree. The way to get cooperative multitasking today is to put code
into a timer event. As far as the programmer is concerned, he or she didn't
make any "threading" calls. Writing a routine that calls other routines is
not multitasking at all. The original routine places items on the stack and
the subroutine is called. There is only one thread.

The entire rest of your message was excellent, BTW.

--
--- Nick Malik [Microsoft]
MCSD, CFPS, Certified Scrummaster
http://blogs.msdn.com/nickmalik

Disclaimer: Opinions expressed in this forum are my own, and not
representative of my employer.
I do not answer questions on behalf of my employer. I'm just a
programmer helping programmers.
--
 
Frans Bouma said:
Cor Ligthert wrote:
I don't know what IBM nor JCL (?) has to do with it, but the thing is
this:
on 16 bit windows (win3.xx), the scheduler worked with 16bit processes
only and basicly scheduled the processes/threads once the thread who had
the processor gave execution back to the scheduler. This is called
'co-operative' as multi-tasking was depending on the cooperation between
applications. I.e.: if an application didn't give execution back to the
scheduler, the system 'hanged' (no other threads got the CPU) unless a
non-maskable interrupt was triggered.

on 32bit windows based on the win95 kernel (win9x, winME) the scheduler
worked pre-emptively. This means that the whole system was divided in
32bit processes and the scheduler scheduled the threads of these processes
using a priority stack and some other protocols (mostly round-robin). Each
thread in the system was given a fixed amount of time, after that, the
scheduler simply took teh CPU away from the thread and the thread was
physically halted as another thread was given the CPU. It depended on the
priority/place in teh thread queue which thread was given the CPU. This is
totally different from the 16bit OS, as the scheduler decided which thread
was given the CPU, not the thread currently running.

16bit applications were all ran in a single 32bit process. 16bit processes
on 16bit windows shared the system memory so they all had access to
eachother memory and as they were all scheduled as 1 process, their
multitasking was still depending on co-operation, as the whole 16bit
process space was given the CPU, inside it it was then decided which
process got the CPU, i.e.: the last process which had the CPU.

On 32bit windows based on the NT kernel, this is not that different,
except from teh fact that 16bit processes are run inside a virtual
machine.

Co-operative multi-tasking is stupid. It easily hangs the machine.
(win9x/ME also had problems with 16bit processes which stepped on its own
16bit OS libraries (as they all shared the same memory), for example parts
of the shell were 16bit code, so a bad 16bit program could hang the
complete system, as it could overwrite parts of the OS without having the
OS stopping it because of a GPF)

Co-operative multi-tasking is also just a trick to do things 'in parallel'
without having to work with threads. The reason why some people still want
it is that they want to do things in parallel in a synchronious way, as in
pre-emptive multi-tasking it is undefined which thread gets the cpu and
when, so it requires extra code to make asynchronous code work as planned
and debugging that kind of code can be cumbersome.

We all do have synchronous multitasking code today: simply write a routine
and call from that routine your other routines. That's co-operative
multitasking. As I wrote earlier, a state-machine can help you with this.
You can chop up a long running routine into several states and hop between
them using the state machine, which then allows you to add states in
between these 'substates' to get things done in parallel, but in a
synchronous way. Using this I wrote 13 years ago a parallel computing
system for a 120-node sparc cluster (in C) which could schedule and
dispatch jobs on all the nodes, synchronously and in parallel without
having to have a lot of threads and syncing code in place.

Frans.

--
------------------------------------------------------------------------
Get LLBLGen Pro, productive O/R mapping for .NET: http://www.llblgen.com
My .NET blog: http://weblogs.asp.net/fbouma
Microsoft MVP (C#)
------------------------------------------------------------------------

Excellent message Frans.
I just like to add that 16 bit Windows had no notion about threads and
processes, there was no such thing like a thread based scheduler.
The idea about a single address space to run 'several' applications and let
the applications themselves do some sort of task switching was driven by
(amongst others) the availability (or lack of) of resources like CPU memory
and disk at windows 3.x design time and the absolute requirement to be DOS
compatible. Very soon it turned out as a bad design decision and that was
the start of the design of consumer Windows (Windows 95 ...), with it's
backwards compatible 16 bit mode subsystem.

Willy.
 
Nick said:
Hi Frans,

I do have one small disagreement with your otherwise excellent description.
I disagree. The way to get cooperative multitasking today is to put code
into a timer event. As far as the programmer is concerned, he or she didn't
make any "threading" calls. Writing a routine that calls other routines is
not multitasking at all. The original routine places items on the stack and
the subroutine is called. There is only one thread.

Ok, agreed, my description was more targeted towards teh topicstarted
which wants co-operative multi-tasking, something you can only
accomplish in a pre-emptive system withIN your own code, so simply
create a sequence of statements which give the suggestion of 'doing more
things at once'. A good example is the single-threaded loop which
updates a progress bar using Application.DoEvents() ;).

But I agree with you, that if you want co-operative multitasking with
other objects, not written by you, you indeed need a timer.
The entire rest of your message was excellent, BTW.

thanks! :)

Frans.
--
 
Back
Top