Windows 3.x can run multiple applications at the same time as long as all of the programs are well behaved. Windows 3.x is a cooperative multitasking environment. Each application must tell the system that it has finished processing, before any other application can start, by calling GetMessage. If an application does not yield control, then the user will not be able to switch to another program.
How do you prevent an application from hogging the system? The two basic approaches are to use PeekMessage or a timer.
PeekMessage allows the application to continue processing until another application needs to process a message. After performing a small part of the job, your application must yield to Windows by using WaitMessage. This gives other programs a chance to use the system. When the system is available again, you can process another small part of your job.
When you use a timer, the application executes a chunk of the job whenever you receive a message from the timer.
Obviously, both of these approaches add unnecessary complexity to the application. Applications are not always made up of a series of discrete tasks. Even when an application is easily divided into discrete tasks, you must still keep track of what work has been completed and deal with any errors.
Cooperative multitasking can sometimes make it more difficult to develop client/server applications. If an application makes a synchronous call to some function that performs a lengthy process, Windows 3.x appears to "freeze" until that function finally returns and can yield control back to Windows 3.x. Since synchronous functions like dbsqlexec do not return until the specified query has been compiled and executed, complex queries against very large databases may take some time to complete. SQL Server provides functions that allow any application to communicate asynchronously. dbsqlsend sends a command batch to SQL Server but does not wait for the database processing to complete before it returns control to the caller. It returns it immediately. You can call dbdataready periodically to see when your command has finished, and then call dbsqlok before processing the result set. This makes it much easier to create very responsive applications on the Windows 3.x platform.
Windows 95 and Windows NT provide preemptive multitasking. This means that the operating system can preempt your program at any time, give the CPU to another process, and then return control back to your program's execution without your knowledge or permission. Preemptive multitasking takes the burden off the application developer and puts it on the operating system—where it belongs. Win32 applications do not monopolize the system. The scheduler will preempt them whenever a higher priority process is waiting.