Sharing a Timer between multiple windows

I’m not at a stage where I have things pretty well sorted (I’ll summarize in a follow-up post), but the issue that has me stumped is that I need to pause the action in some cases and use the ShowModal call to wait for user feedback and choice. Where I’m scrambled today is that is appears that some times the ShowModal doesn’t pause the action while other times it does.

The question is - should a dialog (MessageDialog) opened with ShowModal via a Timer pause the app, or is it now a special case and the app continues?

It looks like I need to set a boolean value and loop until the boolean is false and then check the value returned by the user’s choice?

ShowModal should pause the code that called it. Since you’re calling it from a Timer, it will pause the main thread. Other threads are free to execute.

That’s what I uncovered last night - the Main Loop was pausing and the thread was continuing. The reason I saw “sometimes” pausing was because a few instances that required pausing were actually running in the main loop rather than a thread.

That kind of debugging is quite exhausting mentally :o

Time to create the do nothing and wait loops…

I remember having a problem with 2 ShowModals (one after the other). Had to change this to my second “staple” spaghetti code solution: notifications. Something like this here: https://github.com/declaresub/NotificationCenter . Makes nice code but I found no better solution so far.

I’ve added to the example I posted. I added a QueryTimer and Queryable interface. It works well, but there is a problem with thread.resume not working if another thead is suspended in between, like

thread1.suspend
dialog1.showmodal
thread2.suspend
dialog2.showmodal
dialog1.close
thread1.resume //doesn’t resume
dialog2.close
thread2.resume //now both resume

I have to assume it has to do with multiple modals being shown… if I resume the last on suspended it works, just seems to be something to do with the order of suspension/modals? I think it might be a bug, but I’m not sure where it is…
UITimer

Jim - just ran into a similar situation where an event occurred in two thread instances and the user responded to the first, but it didn’t resume until they responded to the second.

This made me drop that method and stick with the do nothing loops until the Self.ModalClosed boolean was set True. That allows the order of the pauses to be of no concern.

How in the world would you get 2 modals shown at the same time? Unless you were showing a modal from a thread, which is a big no-no. And I don’t think you can show a modal from a modal, either.

It was the 2 threads calling 2 different timers on 2 different windows.

Right, thread1 starts timer1 that shows modal1. same for thread2…
I think it’s probably better to avoid using built-in modality when dealing with threads.
I just updated that project file with a workaround that I think is pretty smooth using a variation of the do-nothing loop.

result=UIFromThread.RunQuery(self.myQueryDialog,self,"Default?")
myQueryDialog is a sheet that implements the queryable interface.
The module creates a timer, which shows the dialog with a default value, then returns the result. Meantime, the calling thread sleeps a lot waiting for the timer to finish. Pretty effective I think.
UITimer

Have you tried creating a thread pool using Derks thread subclass? It allows for ui-threading by treating the thread as a timer :slight_smile:

Cocoa Xojo introduced some situations where a modal dialog would still let the main event loop run.

@Matthew: the threads aren’t a problem, but getting information from a to b when I need it. Examples:

  1. The Cocoa controls of MBS implement their events in a subclass. So I need a notification back to the window.
  2. My printing is done via loading html into a window which is then converted to pdf. You get a nice instant crash if you do this in a thread. So I use the main thread with notifications.
    And so on.

UNCLE!

A sincere thanks to all who have contributed to my request, but because of the heavy changes required to get any of this sorted - over 110 unfruitful hours at this point, I’m throwing in the towel and moving back to Carbon. Aside from being able to say that the app’s a Cocoa app, Cocoa brings nothing to the table for me but serious indigestion.

I know all of the potential issues and I know there are many that will tell me that my app’s just a problem waiting to happen, but it’s been running as is with no issue on thousands of systems for over 5 years. It even runs without incident on 10.9 (meaning I can support 10.4.11 through 10.9 with one app. I don’t chalk it up to luck, but rather the manner in which I wrote the app - even though it’s somewhat event driven, the monitor operations where these problematic dialogs appear are structured, top down code. The only reason that I even bother with threads is because the user can execute multiple monitors at once and I want to keep their properties encapsulated within the particular monitor. The only controls being manipulated from the thread are the controls related to that specific monitor operation’s Container, so there is no way that thread3 could accidentally interact with the UI controls from thread1 - in effect, I have multiple, separate instances of my app running with a master app.

So why bother with one instance of a timer then ?
Create a timer in each thread (create it in code when you create the thread) and put a callback on the thread (using add handler) that does the UI update from that threads timer.
Done.
The thread can now do it’s thing & the timer can read whatever “progress” it needs directly from the thread when it’s action event runs & update the UI.

Because the timer still runs in the main loop and it doesn’t pause the thread for user interaction.

Later this year we’ll be rewriting the project from the ground up (moving to database and AVFoundation), so we’ll tackle the UI updating and Cocoa necessity then.

You control the thread and the timer in the same spot so you could have the timer pause the thread (suspend it) do the interaction and then resume it once the interaction is done
This still presumes a fair bit about how much variability there is in the interaction etc but it seems more likely to be able to do that than to have one shared timer across multiple windows & threads