If your code needs to cause visible updates whilst continuing to do further computation, then you should run your computation in a separate thread which is not directly associated with the CAPI window.
Consider the following example where real work is represented by calls to
sleep
:
(defun change-text (win text)
(setf (title-pane-text win)
text))
(defun my-callback (win)
(change-text win "Go")
(loop
for i from 0 to 20 do
(change-text win (format nil "~D" i))
(sleep 0.1)))
(defun test ()
(let* ((p1 (make-instance 'title-pane
:text "init"))
(p2 (make-instance
'button :text "Go"
:callback-type :none
:callback #'(lambda ()
(my-callback p1)))))
(contain
(make-instance 'row-layout :description (list p1 nil p2))
:width 200 :height 200)))
(test)
and note that the updates do not appear until
my-callback
returns. This is because it uses only one thread.(defun my-work-function ()
(let ((mbox (mp:ensure-process-mailbox)))
;; This should really have an error handler.
(loop (let ((event (mp:process-read-event mbox
"Waiting for events")))
(cond ((consp event)
(apply (car event) (cdr event)))
((functionp event)
(funcall event)))))))
(setf *worker*
(mp:process-run-function "Worker process" ()
'my-work-function))
(defun change-text (win text)
(apply-in-pane-process win
#'(setf title-pane-text)
text win))
(defun my-callback (win)
(mp:process-send
*worker*
#'(lambda ()
(change-text win "Go")
(loop
for i from 0 to 20 do
(change-text win (format nil "~D" i))
(sleep 0.1)))))
(test)
again: you should see the updates appear immediately.A real application might also display an Abort button during the computation, with a callback that aborts the worker process.
CAPI User Guide (Macintosh version) - 30 Aug 2011