There are a number of special rules that govern how and when threads can receive user input. In the following discussion, the phrase ACCEPT statement refers specifically to formats 1, 2, and 7 of the ACCEPT statement. These are the forms that retrieve the user's input.
When a thread attempts to execute an ACCEPT statement, two rules determine if that thread is allowed to proceed:
If an ACCEPT does not meet both of these conditions at the time that it would normally execute, its thread is suspended. The thread will remain suspended until both conditions are met (at which time the thread resumes and the ACCEPT executes).
These rules apply only if there is more than one thread. If a suspended thread becomes the only remaining thread, then it automatically resumes execution.
If a thread suspends due to rule (2), it will suspend forever unless its window becomes active. This can happen in one of two ways: (a) another thread activates the window, or (b) the user activates the window. Arranging for the latter is much more common. It is the case where you want to give the user the ability to work in multiple windows at once, freely switching between them.
To create windows that the user can activate at will, you describe the windows as MODELESS when you create them. A modeless window allows the user to activate another window (the other type of window, called modal, does not allow the user to activate another window). When the user activates a modeless window, by clicking on it or using the host's method, the runtime generates a CMD-ACTIVATE event. In a single-threaded program, the program must detect this event and ACCEPT something in the appropriate window in order to activate that window. In a multithreaded program, there is a second option. To use this option you code your program in such a way that each modeless window runs in a separate thread, and you use the phrase LINK TO THREAD or BIND TO THREAD when you create each window. This phrase instructs the runtime to handle the CMD-ACTIVATE events on its own. In this arrangement, when a CMD-ACTIVATE event occurs, the runtime suspends the current thread and activates the new window. The thread controlling the newly active window then resumes execution. Technically speaking, the thread running the ACCEPT in the newly active window can leave the suspended state because it meets rules (1) and (2) described above.
This automatic runtime handling allows you to easily manage multiple windows. Each window is contained in a thread that need only manage that one window. The threads do not need to be aware of each other or know which window is active. If the threads have some need to communicate among themselves, they can do so with messages. See Thread Communication for more information.
Here is an example. The following program presents a maintenance screen for a data file. It also pops-up a window that has a list of all the records in the file. The user can update a record on the maintenance screen, and can select records from the list. When the user selects a record, the maintenance screen is updated with the selected record.
MAIN-LOGIC. PERFORM INITIALIZE DISPLAY STANDARD GRAPHICAL WINDOW, LINK TO THREAD PERFORM THREAD SEARCH-THREAD, PERFORM UNTIL DONE PERFORM DISPLAY-RECORD ACCEPT MAINTENANCE-SCREEN ALLOWING MESSAGES FROM LAST THREAD ON EXCEPTION IF KEY-STATUS = W-MESSAGE PERFORM SAVE-CURRENT-RECORD RECEIVE RECORD-NUMBER FROM LAST THREAD END-IF END-ACCEPT END-PERFORM PERFORM SHUT-DOWN STOP RUN. SEARCH-THREAD. DISPLAY FLOATING GRAPHICAL WINDOW, MODELESS, LINK TO THREAD HANDLE IN H-SEARCH-WINDOW PERFORM DISPLAY-SEARCH-LIST PERFORM UNTIL 1 = 0 PERFORM ACCEPT-SEARCH-LIST SEND RECORD-NUMBER-SELECTED TO LAST THREAD END-PERFORM.
This example shows how using threads can simplify managing multiple windows. In it, one thread manages the main window, and one manages the search window. The search window is very simple, its thread sits in an infinite loop fetching a list item from the user and sending it to the main thread. The main thread sits in a loop accepting the main screen. If a message arrives from the search thread, it saves the current record and retrieves the record sent from the search window. By using multiple threads, each piece of your window-handling code stands alone. If it were written as a single-threaded program, the two loops accepting the windows would have to be combined into a single loop, with a state variable tracking which window is currently active.