how to force a refresh on 64bit?

When loading an app I show a progress window. I update the progress when I move from one portion of the loading to another or when enough files have been processed that I want to update the progressbar. Prior to moving it to a 64 bit app I called self.refresh after I had updated the info and the window drew itself.

This no longer happens in 64bit. refresh, and even updateNow seem to have no effect on the window until my code completes.

Is this a bug? or is there a new way to do this in a 64bit app. The window documentation for refresh or updateNow doesn’t contain any warnings about doing it from within a 64bit app.

This is a MacOS 64 bit compile.

I see a similar thing. Something is different with refreshing.
In my case when dropping a large amount of files onto a Listbox I Update the Listbox header every second and do a refresh to show how much are imported up to that point.
This works with 32-bits compiled Apps. Not in 64-bits.

there was a recent post that suggested that having ANY timer fire would allow the screen to update.
Sounds barmy and buggy to me, but try firing a timer as a one shot deal .

Or even (whisper its name) app.doevents?

(You said the app.doevents word. :slight_smile: )

I tried the timer but no luck for me. Even tried to put refresh and invalidate in the timer but nothing.
I think however that this had to do with El Capitan overall. And not specifically 32 or 64 bits.

wel app.doevents definitely does cause the window to update my changes… And I could do that during the startup event without the re-entrant problems of events other places in the code because there aren’t any sockets or timers or otherthings created yet. Still, that is not the solution I would prefer…

I’m not sure a timer will fire at all while I’m running in a long loop.

I suppose the proper way to do it would be to move all my loading code to a thread. But yuck, all that work just because I can’t call a refresh method and have it refresh? There has got to be a way to make the window draw that isn’t verboten.

It definitely works properly on El Capitan when compiled to 32 bit.

There is…

heh, if thats the new way to do it then they will have to remove the refresh handler from the 32 bit version then :wink: They are supposed to be similar right? :wink:

I believe that it’s been officially accepted as a bug <https://xojo.com/issue/41899>

The behavior is verified, but it isn’t necessarily a bug (or a bug that we can fix). I haven’t taken a look yet, but I’m pretty sure we leave this entirely up to the OS and if it ignores the request, there’s not much we can do about it.

it does change who we have to report the bug to… :wink:
i did some experimenting around calling the enableUpdates for the NSWindow, then refresh and then disable updates again. That DID result in an update, but it also resulted in an exception as an out of sync number of enable vs disable calls were made. So maybe that is the bug, either in the OS or in the framework.

Maybe time to refactor simply with a timer instead of cramming the action in a single event. Just like for ProgressBars…

I tried this morning real quick. The timer won’t fire when also in the main thread.

It is not quite as simple as what one would do to update the UI from a thread.

You cannot simply replace the label text update by the same in the action event of a zero ms timer. The code itself must be running in the timer Action :

In Timer1,10 ms period, ModeOff :

[code]Sub Action()
static stop as integer = ticks + 300

if ticks < stop then
Label1.Text = format(ticks, “###”)
else
me.mode = Timer.ModeOff
end if
End Sub
[/code]

In a button :

Sub Action() Timer1.Mode = Timer.ModeMultiple End Sub

Essentially, what that does is replace calls from within one event that will not refresh, by separate calls, each in the Action event of the timer, so each refreshes naturally.

This is typical of moving from procedural code to event driven. Not terribly complex (the code is mostly identical), but it is a completely different approach.

Michel,
I don’t see how this is akin to event/object coding. If I press a button (that is an event), then that event should trigger something (say a refresh). If I rather “schedule” something, then I am going to an “RTOS” style programming, where now I am trying to create my own scheduling for actions (not events) to happen on top of the OS scheduling. Maybe my interpretation is incorrect, but I think that is moving away from event/object programming. I am not saying your solution is not a possible work-around, but it looks a lot more like a “work-around” to something broken (by either OS or Programming tool) than adopting an object/event driven model.

Threads cannot touch UI directly
So you need something that is IN the thread (so it has access to the threads properties etc) but is not run as part of the threads code being run

The VERY simple case is

  1. add a property to a thread subclass - mTimer as Timer

  2. add a private method that will be run as the Action event of the timer

          Private Sub HandleTimerAction(whichTImer as Timer)
               // DO YOUR UI UPDATES HERE !
          End Sub
  1. in the thread subclass Run event create the timer
         Event Run()
              mTImer = new TImer
              AddHandler mTimer.Action, AddressOf HandleTimerAction
              mTimer.Period = 1
              mTimer.Mode = Timer.ModeMultiple
      
               // do whatever you thread needs to do

              // until you're done

              mTimer.Mode = Timer.ModeOff
              RemoveHandler mTimer.Action, AddressOf HandleTimerAction
       end

Use this subclass where you might have used a regular thread

Timer actions ALWAYS run on the main thread
But since this timer is part of the thread it has access to whatever the thread has access to

[quote=236685:@LangueR]Michel,
I don’t see how this is akin to event/object coding. If I press a button (that is an event), then that event should trigger something (say a refresh). If I rather “schedule” something, then I am going to an “RTOS” style programming, where now I am trying to create my own scheduling for actions (not events) to happen on top of the OS scheduling. Maybe my interpretation is incorrect, but I think that is moving away from event/object programming. I am not saying your solution is not a possible work-around, but it looks a lot more like a “work-around” to something broken (by either OS or Programming tool) than adopting an object/event driven model.[/quote]

Whatever. Refresh is simply a remnant of procedural programming. Just like DoEvents. Using a timer is the proper way to do visual progress indicators, not a workaround.

My thoughts exactly :slight_smile:

I thought the OP was not talking about threads.

BTW, event programming <> OOP. They can be related, but that is not an obligation. The example I posted is not OOP.

[quote=236696:@LangueR]My thoughts exactly :slight_smile:
I thought the OP was not talking about threads.[/quote]

He’s not
This is “how to avoid having to use refresh at all”

All the rest of my code is event driven :wink: I see people here post all the time how they want to send and receive things from sockets in the same line of code execution and I always groan too. I have no trouble using the events async and a state machine affair for managing complex protocols and the like.

This particular problem is biting me in 2 places. During my app.open event when I have to load a large database of data and give a little feedback as to the progress, and when people do a manual saving or exporting of this database. In the case of the open event there aren’t any events that can be expected and nothing else is happening in the app yet and so doing it all inline in the main thread doesn’t feel like a problem to me, and it hasn’t been for the last 10 versions of Xojo or so :wink: In the second case of a human selecting to export the database I have to stop all other code execution and events anyway as the database has to have all it’s caches and datas written to disk, it can’t be accepting new data in the middle of the save or very strange things will happen. So there I WANT it to be blocking and inline and all in one process.

Whenever I move to the next dataset to read I update the status label display that says what it’s loading or saving, and once a second or so I update the progress bar.

This is really not an example of something that needs to be threaded or isn’t event driven. To thread the first one would not be that difficult as there isn’t anything else happening yet that could bump into it. I would just have to change all the accessors of the windows so that they simply set local variables in the window I could update from in a timer in the window. The second example I want everything else to stop while I’m working on the database so I would have to block the main thread from any events coming in on any sockets or other things. I’m sure that could be done.

In both those cases I don’t feel like I should have to do that though. I’m working around what is pretty obviously a bug. I do not believe that apple means for 64 bit apps to be unable to force a window refresh when the developer wants to do so do they? When they do it perfectly in 32 bit apps? So it’s either a bug in Xojo’s libraries or in Apple’s and if I send a day or two moving these things to threads and re-testing to make sure I’m not going to get a socket event while the database is saving it feels like a waste of time.

I should be able to force a window update when I want to shouldn’t I? This is different I think from the other changes that affect when drawing happens in OSX now. I see those strange black windows and such in the 32 bit version of the app too. But in the 32 bit version I can still call to refresh or updateNow and make the window draw itself. Under a 64 bit compile that call does nothing. It’s a 64 bit compile bug, either xojo’s or apples.