User interface / The interaction model |
When the program executes an interactive instruction, the GUI front end can send action events based on user actions. When the program performs a long process like a loop, a report, or a database query, the front end has no control. You might want to permit the user to stop a long-running process.
To detect user interruptions coming from a GUI front-end, you define an action view with the name 'interrupt'. When the runtime system takes control to process program code, the front end automatically enables the local 'interrupt' action to let the user send an asynchronous interruption request to the program.
Do not confuse the 'interrupt' special action with the SIGINT signal handling that can be controlled with DEFER INTERRUPT. It is good practice to use DEFER INTERRUPT/QUIT in your programs. When not using DEFER INTERRUPT, if the program enters in a long running procedure, a button with the action name 'interrupt' will become active, the user can then press on that button, and the runtime system will process the interruption event as a SIGINT signal, which will stop the program, since DEFER INTERRUPT is not used. This will not happen when a dialog is active, because the 'interrupt' button will be automatically disabled in that context. Consider using DEFER INTERRUPT and test INT_FLAG to properly handle user interruptions, and avoid immediate program termination.
The front end can not handle interruption requests properly if the display generates a lot of network traffic. In this case, the front end has to process a lot of user interface modifications and has no time to detect a mouse click on the 'interrupt' action view. A typical example is a program doing a loop from 1 to 10000, just displaying the value of the counter to a field and doing a refresh. This would generate hundreds of AUI tree modifications in a short period of time. In such a case, we recommended that you calculate a modulo and display steps 10 by 10 or 100 by 100.
-- db_busy.per LAYOUT GRID { Database query in progress... [sb ] } END END ATTRIBUTES BUTTON sb: interrupt, TEXT="Stop"; END
MAIN DEFINE oc INT DEFER INTERRUPT OPTIONS SQL INTERRUPT ON DATABASE stores OPEN FORM f FROM "db_busy" DISPLAY FORM f CALL ui.Interface.refresh() WHENEVER ERROR CONTINUE SELECT COUNT(*) INTO oc FROM orders WHENEVER ERROR STOP IF SQLCA.SQLCODE == -213 THEN ERROR "Database query has been interrupted..." END IF END MAIN