WAIT-FOR statement (.NET and ABL)
- Last Updated: October 16, 2024
- 14 minute read
- OpenEdge
- Version 12.8
- Documentation
(Windows only; GUI for .NET)
This WAIT-FOR statement instructs the AVM to stop executing the current block and remain in a wait state (blocking) until a .NET method that it calls returns. The AVM continues to respond to all incoming ABL events (see the WAIT-FOR statement (ABL only) reference entry) as well as .NET events, and it executes any associated triggers, event procedures, or .NET event handlers while in this wait state.
Syntax
|
- object-reference
-
A reference to an object that generally inherits from the .NET class
System.Windows.Forms.FormorSystem.Windows.Forms.CommonDialog. OpenEdge provides a particular subclass ofSystem.Windows.Forms.Form—the Progress.Windows.Form class—which you can use to create .NET forms in an ABL session that co-exist more naturally with ABL windows. - type-name
-
The type name of a .NET class that provides a static blocking method, most commonly
System.Windows.Forms.Application. With an appropriate USING statement, you can also specify the type by its unqualified class name (Application). - method-name
-
The name of a .NET input-blocking method that the WAIT-FOR statement calls, which is typically
Run(a static method onSystem.Windows.Forms.Application), or by .NET convention,ShowDialog(an instance method onSystem.Windows.Forms.FormorSystem.Windows.Forms.CommonDialog). - parameters
-
Parameters for the method specified by method-name.
- SET return-value
-
Provides the return value from the method, method-name( ), which is set when the WAIT-FOR statement completes execution. The return-value can be a variable, property, or field that has the same data type as the method-name( ) return value, typically
System.Windows.Forms.DialogResult.To use this option, method-name
( )must be a non-VOID method. If you specify this option for a VOID method, such asSystem.Windows.Forms.Application:Run( ), ABL raises a compile-time error.For more information on .NET input-blocking methods that you can call in the WAIT-FOR statement, see the notes of this reference entry.
Example
The ABL-derived .NET class, r-WaitForms,
inherits the Progress.Windows.Form class to implement
a non-modal .NET form. When you try to close the displayed form, a dialog box appears that
prompts if you want the form to complete closing or not. If you choose to complete closing,
the form closes. If you choose to cancel the closing, the form remains displayed, and you
can try to close the form, again.
When you instantiate r-WaitForms, it
initializes and subscribes a handler (the Form_Closing( )
method) to the FormClosing event of the form. You can then
display the form by calling the DoWait( ) method on the
r-WaitForms instance. This method executes the WAIT-FOR
statement, which calls the .NET input-blocking method System.Windows.Forms.Application:Run( ). (For more information on this method,
see the notes.) When you try to close the displayed form, this causes the non-modal form to
publish its FormClosing event, which executes the Form_Closing( ) method to handle the event.
r-WaitForms.cls
|
The Form_Closing( ) method passes INPUT
parameters from .NET for the FormClosing event. One of
these parameters (e) is a System.Windows.Forms.FormClosingEventArgs object, which contains a Cancel
property whose setting allows the event handler to either complete the FormClosing event or interrupt and cancel the FormClosing event. To determine how to set this property, the
event handler instantiates, initializes, and displays another Progress.Windows.Form class (rDialog)
as a modal dialog box.
The dialog box contains two buttons, rOKButton and rCancelButton, whose DialogResult properties are set to the System.Windows.Forms.DialogResult enumeration values OK and Cancel,
respectively. The event handler displays rDialog as a
modal form by executing the WAIT-FOR statement, which calls the modal input-blocking method
System.Windows.Forms.Form:ShowDialog( ). (For more
information on this method, see the notes.)
When you click one of the two dialog buttons, this causes the dialog box
to close and the ShowDialog( ) method to return. This
automatically sets the DialogResult property on rDialog to the value of the DialogResult property on the button that you have clicked and also returns the
same property value as the value of ShowDialog( ), which
the WAIT-FOR statement assigns to the variable, enDialogResult. The event handler then uses the static AreEqual( ) method on the Progress.Util.EnumHelper class to test the value of
enDialogResult and set the e:Cancel property to either complete the FormClosing event or cancel the FormClosing
event and leave the non-modal form open for further input.
System.Windows.Forms.MessageBox:Show( ) display a message box similar to the ABL
MESSAGE statement with the VIEW-AS ALERT-BOX option.To instantiate r-WaitForms and display
the non-modal form, you can thus run a procedure with code like this:
|
Notes
- A non-GUI ABL session cannot visualize .NET form and control objects
and cannot block for GUI or non-GUI .NET events. So, you cannot invoke this WAIT-FOR
statement (calling a .NET input-blocking method) within a non-GUI, Windows ABL session,
including a:
- Character mode (CHUI) client
- Batch-mode client
- Application server session
- If you use any .NET forms in an ABL session, you can execute only one .NET WAIT-FOR statement that processes events for all .NET
non-modal forms and their controls. This statement must be the first WAIT-FOR statement
for processing non-modal events in your application. Following this statement, from event
handlers and trigger blocks, you can execute multiple input-blocking statements to process
any modal .NET form or ABL dialog box. ABL events for non-modal windows and their child
widgets, or for non-GUI ABL features, such as asynchronous remote procedure calls and
socket operations, all work in the context of this single non-modal .NET WAIT-FOR
statement. CAUTION: Using stacked input-blocking statements other than for dialog boxes is not recommended. If you do so, you must take special care to ensure that any WAIT-FOR statements that you simultaneously execute to process non-modal events complete their execution in reverse order of invocation. Otherwise, your application will have unpredictable behavior. Also, in certain contexts (such as within a user-defined function or non-VOID method), if you execute an additional input-blocking or event-processing statement while displaying an ABL non-modal window together with .NET non-modal forms, the AVM raises the STOP condition.
- To block on any number of non-modal .NET forms (and ABL windows), you
must use a WAIT-FOR statement that executes the
System.Windows.Forms.Application:Run( )input-blocking method (as shown for the example class,r-WaitForms):WAIT-FOR System.Windows.Forms.Application:Run ( [ form-object-ref ] )You can specify form-object-ref as an object reference to a single .NET non-modal form object, on which the WAIT-FOR statement blocks, displays, and waits to close. If you specify form-object-ref, the statement also displays any additional non-modal forms that you have previously initialized by setting their Visible properties to TRUE or by invoking their
Show( )methods. However, .NET automatically displays form-object-ref, itself, without having to set its Visible property or run itsShow( )method. You can also use triggers, event procedures, and .NET event handlers to create and display additional non-modal .NET forms (or ABL windows) after the WAIT-FOR statement blocks for events.The conditions for unblocking this WAIT-FOR statement differ, depending on whether you specify form-object-ref. However, whatever conditions unblock the WAIT-FOR statement also automatically close any open .NET forms. This is different from ABL windows, which you must explicitly open and close using ABL statements or widget attributes without regard to the execution of a WAIT-FOR statement.
With form-object-ref, the WAIT-FOR statement unblocks and continues execution with the following statement if one of the following actions occurs:
- Your application explicitly calls the form-object-ref
:Close( )method, which automatically calls theDispose( )method to garbage collect the form. - The user clicks the form Close (X) button in the upper right corner of the form-object-ref form, and you do not cancel the action in a handler for
the
FormClosingevent, as in the example. This action also automatically calls the form-object-ref:Close( )method. - Your application calls the
System.Windows.Forms.Application:Exit( )method.
When you use any of these techniques to unblock the WAIT-FOR statement, all currently displayed non-modal forms close, in addition to the form specified by form-object-ref, and including any non-modal .NET forms that were created and displayed after the WAIT-FOR statement blocked.
CAUTION:If you are executing the READKEY statement within a trigger or event handler while blocking on a form-object-ref, and the user clicks the form Close (X) button, the ABL application shuts down unconditionally. For example, the following READKEY loop can cause this shutdown to occur:
DO WHILE LASTKEY != KEYCODE("F3"): READKEY. IF LASTKEY = KEYCODE("F3") THEN RETURN. END.This shutdown occurs because .NET generates a WM_QUIT message in response to clicking the Close (X) button that READKEY interprets (by design) as a message to shut down the application.
CAUTION: You might have a problem displaying message boxes after invokingApplication:Exit( )orApplication:ExitThread( ). One way this can happen: if you use any two of the techniques for unblocking the WAIT-FOR, such as by callingClose( ), then callingApplication:Exit( ), any subsequent executions of the MESSAGE statement with the VIEW-AS ALERT-BOX option or any subsequent calls toSystem.Windows.Forms.MessageBox:Show( )might not display the specified message box and the user will hear a beep sound instead.If you do not specify form-object-ref, the statement displays and blocks for input on any non-modal forms that you have previously initialized by setting their
Visibleproperties to TRUE or by invoking theirShow( )methods. Without form-object-ref, you also do not need to have a .NET form instantiated before you execute the WAIT-FOR statement. Without any non-modal .NET form created, this statement processes ABL events until you create and initialize your first .NET non-modal form for display in an associated event handler or trigger, at which point the same WAIT-FOR statement processes both .NET and ABL events.Also, if you do not specify form-object-ref, the WAIT-FOR statement unblocks and continues execution with the following statement only when you invoke the
System.Windows.Forms.Application:Exit( )method at some point in the ABL session. This method closes all non-modal .NET forms that are currently open before unblocking the WAIT-FOR statement. Note that using this technique, you must be sure to create and initialize at least one .NET form or ABL window (non-modal or modal) so there are active components to work with during the input-blocking state. Otherwise, the blocking WAIT-FOR statement blocks indefinitely or until the user presses CTRL+BREAK.Note: When working with any displayed non-modal form, except the form specified by form-object-ref, the user (using the Close (X) button) or the application (using theClose( )method) can close the form. However, this does not by itself unblock the blocking WAIT-FOR statement. If you want the WAIT-FOR to unblock other than by closing the form specified by form-object-ref, your application must callApplication:Exit( ). - Your application explicitly calls the form-object-ref
- To block on a .NET modal dialog box, you must use a WAIT-FOR statement
that executes the
ShowDialog( )input-blocking method on the specified form object (as shown forrDialogin the example class, r-WaitForms.cls):WAIT-FOR dialog-object-ref:ShowDialog ( [ parent-form ] )This causes the WAIT-FOR statement to display the form specified by the dialog-object-ref object reference, and block for input on that form as a dialog box. You can also specify the object reference of a form (parent-form) that becomes the parent of the dialog box referenced by dialog-object-ref. (This allows the .NET dialog box to display centered over the parent form.)
Note that by convention, every .NET class that can implement a modal dialog box has a
ShowDialog( )method, such asSystem.Windows.Forms.FormandSystem.Windows.Forms.CommonDialog, as well as classes that derive from them, likeSystem.Windows.Forms.OpenFileDialog. Therefore, this syntax for the WAIT-FOR statement allows you to open all these different types of dialog boxes.Note: TheSystem.Windows.Forms.MessageBoxclass does not work this way. Instead, it is similar to the MESSAGE statement with the VIEW-AS ALERT-BOX option, which handles its own input without events. Similarly, you can only open aMessageBoxby invoking its staticShow( )method outside of a WAIT-FOR statement.With dialog-object-ref:
ShowDialog( ), the WAIT-FOR statement unblocks and continues execution with the following statement if one of the following actions occurs:- The user clicks the dialog box Close (X) button in the upper right corner of the dialog box.
- You set the dialog-object-ref
:DialogResultproperty (if the form class supports it) to a validSystem.Windows.Forms.DialogResultenumeration value. - You call the dialog-object-ref
:Close( )method. Note that calling this method also automatically calls theDispose( )method on the form, making the form object available for garbage collection.
For any of these actions, the
FormClosingandFormClosedevents are also published on dialog-object-ref, and you can handle theFormClosingevent in order to prevent the form from being closed by canceling the action, as shown in the example.CAUTION: .NET automatically callsDispose( )on a non-modal form when it is closed, unless the form is shown as a dialog box. .NET simply hides the dialog when it is closed. However, the AVM callsDispose( )by default for dialogs that inherit fromProgress.Windows.Form. The AVM does not do this if theDisposeDialogOnCloseproperty of the form is set to FALSE. This can be set on a particular instance or globally using the No Dialog Dispose (-nodialogdispose) startup parameter. One use case for not callingDispose( )is if you want to re-use the form at a later time.At this point, you can check the user response to the dialog box. Note that
ShowDialog( )returns aDialogResult(enumeration) value with the result of the dialog box. You can access this value using the SET option (as shown in the r-WaitForms.cls example) or by checking the dialog-object-ref:DialogResultproperty (if the form object is still available and the class supports it).Note: Not all .NET form classes provide a publicDialogResultproperty—for example,System.Windows.Forms.FileDialog. For a form that does not provide this property, you can handle dialog box results in the following ways: 1) by using the SET option to return the form'sShowDialog( )method value, 2) by using event handlers subscribed to the events that the form provides, for example, theFileOkorHelpRequestevent, or 3) by testing the values of properties that might otherwise be set depending on input to the dialog box, such as theFileNameproperty of theSystem.Windows.Forms.OpenFileDialogobject..NET does not set the dialog-object-ref
:DialogResultproperty automatically except in two cases:- The user clicks the dialog box Close (X) button in the upper right corner, which sets the property to the
DialogResult:Cancelenumeration value. - The user clicks a button (or any control that implements the
System.Windows.Forms.IButtonControlinterface) contained by the dialog box whoseDialogResultproperty you have set with a validDialogResultenumeration value. In this case, .NET automatically sets the dialog-object-ref:DialogResultproperty to the value of the button property.
Otherwise, your application must set the value of dialog-object-ref
:DialogResultdirectly, typically in an event handler. Note that if you want .NET to automatically set the dialog-object-ref:DialogResultproperty from a buttonDialogResultproperty, your application must initialize theDialogResultvalue for the button property before the user clicks a given button. - You can detect that a specific form is closing by handling its
FormClosingevent; you can detect that a specific form has already closed by handling itsFormClosedevent. However, note that theClosedevent does not fire for non-modal .NET forms that you close by callingApplication:Exit( )and that are not specified by the form-object-ref parameter passed to theApplication:Run( )method.CAUTION: Do not delete the ABL object reference to the object (sender) that publishes aFormClosingevent from within itsFormClosingevent handler. This causes theFormClosingevent to be published a second time. If you need to delete the sender for an event that is associated with closing a form before the AVM garbage collects it, execute the DELETE OBJECT statement for the sender within a handler for itsFormClosedevent. - If you specify a non-blocking method in a WAIT-FOR statement, the
method executes and the WAIT-FOR immediately returns, resuming execution with the next
available statement. ABL does not prevent this. However, the WAIT-FOR statement, in this
case, works no differently than invoking the method as a statement by itself.Note: Progress Software Corporation recommends that you donot invoke non-blocking methods using the WAIT-FOR statement.
- The one WAIT-FOR statement that you execute for non-modal .NET forms
after setting their
Visibleproperties to TRUE or by invoking theirShow( )methods, must call theApplication:Run( )method to make the forms visible and usable. If you execute any other form of the WAIT-FOR statement after making non-modal .NET forms visible, such as one that blocks for an ABL event (even a developer event, such as U1 OF THIS-PROCEDURE), the ABL virtual machine (AVM) raises STOP on this WAIT-FOR statement. - You cannot set the
Visibleproperty or call theShow( )method on a modal .NET form before executing a WAIT-FOR statement on theShowDialog( )method. If you execute a WAIT-FOR statement that calls theShowDialog( )method on a modal .NET form that you have previously made visible, .NET raises a run-time exception. - Once you execute a non-modal WAIT-FOR statement that calls the
Application:Run( )method, the statement goes into a wait state that allows any event handlers or triggers to run in response to all types of ABL-supported events, including .NET events, ABL UI events, and ABL non-UI events (such as socket events). In the associated event handlers or triggers, you can then create and display additional .NET non-modal forms (by setting theirVisibleproperties or invoking theirShow( )methods) or ABL non-modal windows (for example, by setting their VISIBLE attributes to TRUE, executing DISPLAY statements, or executing a VIEW statement), and the existing WAIT-FOR statement processes events associated with these new non-modal .NET forms or ABL windows in addition to any other events it is already processing. To open modal dialog boxes (.NET or ABL) from an event handler or trigger, you must execute an additional WAIT-FOR statement for each dialog box that you open. Each such WAIT-FOR statement then blocks until its associated modal dialog box is closed, allowing the event handler or trigger that invoked the statement to resume execution. - .NET does not support blocking for multiple non-modal forms
simultaneously at more than one point in an application. If you attempt to execute more
than one non-modal WAIT-FOR statement that calls
Application:Run( )by invoking a second such WAIT-FOR statement in an event handler or trigger, .NET raises an exception, which in turn raises STOP on this second WAIT-FOR statement.CAUTION: After you execute an additional WAIT-FOR statement that callsApplication:Run( ), even if you trap the STOP condition with ON STOP, .NET does not allow another call toApplicaton:Run( )in the same session. You must exit the ABL session and fix the application to avoid such simultaneous calls toApplicaton:Run( ). - You must execute a separate WAIT-FOR statement for each modal .NET
dialog box or ABL dialog box that you open. The modal nature of each dialog box guarantees
that the corresponding WAIT-FOR statements unblock and resume execution with the
statements that follow them in order of the most recently opened dialog box. However,
while blocking on any .NET or ABL modal dialog box, you cannot then execute a non-modal
WAIT-FOR statement calling
Application:Run( ), even if no previous non-modal WAIT-FOR statement is still in a wait state. Attempting to call a non-modal WAIT-FOR statement while any modal .NET dialog box or ABL dialog box is open raises a run-time error. - If you add non-modal .NET forms to an existing ABL application that
already contains WAIT-FOR statements to process non-modal ABL GUI and non-GUI events,
replace these WAIT-FOR statements (except those that block on ABL
modal dialog boxes) with a single WAIT-FOR statement that calls
Application:Run( ). In order to have an active .NET form in your application, you must execute your latest (and usually only)WAIT-FORstatement in the format that calls a .NET input-blocking method (for example, waiting onApplication:Run( )) so that it is in effect to process .NET events. This allows the application to handle the same ABL events after adding .NET forms that it handled before you added the .NET forms. - You cannot use the APPLY statement to force a WAIT-FOR statement that
is blocking on .NET forms to unblock and continue execution with the statement following
the WAIT-FOR statement. Instead, call the appropriate .NET method (for example,
Close( )orApplication:Exit( )) to unblock the WAIT-FOR statement and continue with the next statement. - To handle a particular .NET event while the WAIT-FOR statement that processes the event is executing, you must subscribe a .NET event handler to the specified event using the Subscribe( ) event method before the event is raised. For more information on event methods and event handlers for .NET events, see the Class Events Reference.
- If an ABL handler for a .NET event raises an unhandled error condition
or throws an error object out of the handler, the AVM does not throw a .NET
Exceptionback to the .NET Common Language Runtime (CLR), but displays a message to the default output device and continues blocking for events. - You cannot invoke the non-modal .NET
System.Windows.Forms.Application:Run( )method or the .NETShowDialog( )method used to display a modal dialog box in any ABL context other than in a WAIT-FOR statement. Any attempt to do so raises a run-time error.
See also
Type-name syntax, USING statement, WAIT-FOR statement (ABL only)