;+ ; NAME: ; YIELD ; ; PURPOSE: ; Yields control to the Windows operating system to allow background processing ; & allows the user to abort or suspend execution. ; ; CATEGORY: ; Utilities. ; MS Windows. ; ; CALLING SEQUENCE: ; YIELD ; ; INPUTS: ; None ; ; INPUT KEYWORDS ; DESTROY If set, Yield destroys the widget base. ; ; OUTPUTS: ; None. ; ; SIDE EFFECTS: ; A button menu widget is displayed. Other Windows processes are given an opportunity ; to execute. ; ; DEPENDENCIES: ; Has an effect only on MS-Windows. May require IDL version >= 3.5 for ; CALL_EXTERNAL to work properly. ; ; PROCEDURE: ; Yield calls widget routines as necessary to maintain a button widget offering the ; choices 'Abort', 'Suspend' and 'Resume'. (The last is initially insensitive.) ; At each call, Yield checks for widget events and also calls the Windows API ; function "Yield" to allow other processes to execute. If no widget events are ; detected, Yield returns to the calling program. If 'Abort' is selected ; Yield writes a message & terminates. If 'Suspend' is selected, Yield sensitises the ; 'Resume' button and goes into a loop waiting for it to be pressed. ; ; EXAMPLE: ; ; Calls to yield should be distributed throughout lengthy computations. ; Yield takes approximately 8 ms to execute on an otherwise idle 486/66. ; (Most of that time is taken for the "Yield" API function.) So to give reasonable ; response in other applications without slowing IDL too much it should be ; called approx once every 0.2 sec. There should be a final call with the ; DESTROY keyword to remove the widget. (Otherwise it should be manually closed.) ; ; The following function (based on one by F Knight) counts the lines ; in a file and optionally calls Yield during processing: ; ; function nlines, file, yield=yield ; ; nl = 0L & tmp='' ; openr,lun,file,/get_lun ; on_ioerror,NOASCII ; while not eof(lun) do begin ; readf,lun,tmp ; nl = nl + 1 ; if keyword_set(yield) then if (nl mod 30) eq 0 then yield ; endwhile ; close,lun ; free_lun,lun ; NOASCII: ; if keyword_set(yield) then yield, /destroy ; return,nl ; ; end ; ; Reading a 3141 line file takes 5.3 second with the YIELD keyword set ; and 4.6 without. (If the references to the YIELD keyword are ; removed entirely, it still takes 4.6 s.) ; ; MODIFICATION HISTORY: ; Mark Hadfield, 3 April 1994: ; Created. ;- pro yield, destroy=destroy common yield_widget, base_id, button_id on_error,2 if strlowcase(!version.OS) ne 'windows' then return if n_elements(base_id) eq 0 then base_id = 0L if not keyword_set(destroy) then begin if not widget_info(base_id,/valid) then $ xmenu, ['Abort','Suspend','Resume'], base=base_id, button=button_id, /row, title='Yield' if not widget_info(base_id,/real) then begin widget_control, base_id, /realize widget_control, button_id(2), sensitive=0 endif event = widget_event(base_id,/nowait) OK = call_external("kernel.exe","Yield") if event.id ne 0 then begin case event.id of button_id(0): begin widget_control, base_id, /destroy message, "Operation aborted. " + $ "You may have to press RETALL to return to the main program level." end button_id(1): begin message, /inform, "Operation suspended." widget_control, button_id(0), sensitive=0 widget_control, button_id(1), sensitive=0 widget_control, button_id(2), sensitive=1 event = widget_event(base_id,/nowait) while event.id ne button_id(2) do begin event = widget_event(base_id,/nowait) OK = call_external("kernel.exe","Yield") endwhile widget_control, button_id(0), sensitive=1 widget_control, button_id(1), sensitive=1 widget_control, button_id(2), sensitive=0 message, /inform, "Operation resumed." end else: message, "Unexpected event from Yield widget." endcase endif endif else begin if widget_info(base_id,/real) then widget_control, base_id, /destroy endelse end