Refreshing a List in a Tight Loop

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
3 messages Options
Reply | Threaded
Open this post in threaded view
|

Refreshing a List in a Tight Loop

Jeffrey Odell-2
In my SUnit Browser, test cases are run in batches when requested by the
user - for example, when the user selects "Run All".  Each time a case is
run, I have the opportunity to refresh the test as displayed in a
MultipleSelectionListView.

I'm attempting to do this by executing:

    listModel updateAtIndex: anIndex

where listModel is an instance of ListModel associated with the list.

One of the effects of executing this is that the icon changes to display
whether the test succeeded of failed.

If I put a halt in the method that executes the code above, the row in the
list updates as one would expect.  However, without the halt, the row will
not get updated until all the tests have run.  Then all the rows get updated
at once.

This indicates to me that a UI callback is not getting processed until my
loop has completed executing.  I've had this kind of problem occasionally in
other Smalltalks and each time there was a way to indicate that the process
should allow callbacks to get handled.

Is there a similar technique in Dolphin Smalltalk 4.0?  Can someone point me
in the right direction?

TIA -

Jeff Odell


Reply | Threaded
Open this post in threaded view
|

Re: Refreshing a List in a Tight Loop

Bill Schwab
Jeff,

> If I put a halt in the method that executes the code above, the row in the
> list updates as one would expect.  However, without the halt, the row will
> not get updated until all the tests have run.  Then all the rows get
updated
> at once.
>
> This indicates to me that a UI callback is not getting processed until my
> loop has completed executing.  I've had this kind of problem occasionally
in
> other Smalltalks and each time there was a way to indicate that the
process
> should allow callbacks to get handled.
>
> Is there a similar technique in Dolphin Smalltalk 4.0?  Can someone point
me
> in the right direction?

Windows is generally happier if you use #queueDeferredAction: to force UI
updates.  The other thing that I tend to do is put a short delay into
background threads that would otherwise be very busy.  Alternatively, you
might be able to queue actions that each process only one item, update the
UI, and then signal a semaphore to allow the background thread to move to
the next item.

Have a good one,

Bill

--
Wilhelm K. Schwab, Ph.D.
[hidden email]


Reply | Threaded
Open this post in threaded view
|

Re: Refreshing a List in a Tight Loop

Blair McGlashan
In reply to this post by Jeffrey Odell-2
Jeff

You wrote in message
news:[hidden email]...

> In my SUnit Browser, test cases are run in batches when requested by the
> user - for example, when the user selects "Run All".  Each time a case is
> run, I have the opportunity to refresh the test as displayed in a
> MultipleSelectionListView.
>
> I'm attempting to do this by executing:
>
>     listModel updateAtIndex: anIndex
>
> where listModel is an instance of ListModel associated with the list.
>
> One of the effects of executing this is that the icon changes to display
> whether the test succeeded of failed.
>
> If I put a halt in the method that executes the code above, the row in the
> list updates as one would expect.  However, without the halt, the row will
> not get updated until all the tests have run.  Then all the rows get
updated
> at once.
>
> This indicates to me that a UI callback is not getting processed until my
> loop has completed executing.  I've had this kind of problem occasionally
in
> other Smalltalks and each time there was a way to indicate that the
process
> should allow callbacks to get handled.
>
> Is there a similar technique in Dolphin Smalltalk 4.0?  Can someone point
me
> in the right direction?

When you send #updateAtIndex: the view responds by invalidating part of
itself for a repaint, but the repaint won't actually happen until the main
GUI process returns to the message loop and pulls out a WM_PAINT message
from Windows. Since you are probably running the tests on the main UI
process the view won't repaint until that main UI process goes idle again.
The reason it works when you put in the #halt is that a new main UI process
is started, which quickly goes idle awaiting input and thus has an
opportunity to do some repainting. You have two basic options:
1) Fork off your processing (i.e. running the tests) onto a background
thread. This will have certain advantages in that you can do other things
while long running tests are under way, but it will mean you'll have to be
careful about the enablement of commands in your UI (probably not too hard
to just disable everything in #queryCommand: if a testing process is
active), and there is always a danger that whatever else one is doing may
interfere with the running of the tests.
2) Request a synchronous repaint rather than waiting for the async. repaint.
You can do this by sending an #update message to the View from the
Presenter.

I'd go for (2), since those who want to live dangerously can easily achieve
(1) by running an expression such as:

tr := TestRunner show. "Now choose a TestCase"
[tr runTests] forkAt: Processor userBackgroundPriority

Regards

Blair