I have a wxApp implementation in which the wxFrame embeds a CEF browser.I have bindings from CEF framework to perform some Javascript bindings. The application shows up the initial screen and loads everything good. However, after a certain delay (not consistent), the app frame becomes non-responsive and does not handle any of the events. I have put up a wxTimer to figure out the amount of time it takes and it varies between 28 seconds to 60 seconds. This is where the timer events are also not called. Now when I press on the x or maximize icon on the window, all the pending events are sent and the application becomes active again.
Here are the options I tried:
Called wxTheApp->ProcessPendingEvents(); on the timer (runs every 1 second)
Tried and looked into onIdle method. This is also getting paused after a while
My guess is that the application main thread is paused for some reason and is not able to revert back unless any of the UI actions are triggering it.
Related
I have a C++ application on Mac OS X. The app runs an event processing with the glfw library on the main thread and reads input and execute commands on a background C++ std::thread.
I am observing a frustrating phenomenon that I cannot explain so far.
If I make a call to a long running function on the background thread, initially that thread is using 100% of a core. But, after it has used a few seconds of CPU (10 seems to be the magic threshold), it gets throttled down to 25%.
If I start a computation run on a thread in the background before starting the glfw event processing loop (the event processing is essentially stuck waiting for events, as I don't even open a window), then it can use 100% for as long as it wants.
My biggest problem is that I have no idea what could be causing this nor how to figure it out. I've tested retrieving the pthread sched_param and changing the sched_priority from what seems to be default 31 to various values between 20 and 60 and it does not help.
I have identified one more condition for the phenomenon to happen:
The background thread has to have read from the terminal. It happens when I run the following background thread and enter a line for the computation to take place:
std::thread cmd([argc, argv, &scriptingRunner] {
for (std::string line; std::getline(std::cin, line); ) {
longComputation();
}
Perhaps App Nap is throttling your application to save energy. To check, open the Activity Monitor program and right-click on the header of the processes table to bring up the context menu, and click on "App Nap" in the context menu to enable the App Nap column; then look at your process in the table and see if its value in the App Nap column switches to "Yes" when the fault occurs.
If you want to disable app nap for your app, see the code listed in the question here.
Is there a way to cancel and reschedule tkinter after() events when the system time is updated, or preemptively update the after() scheduler?
Description
I have a custom GUI created in tkinter using Python3.7 on Raspbian (fork of Debian-Linux for Raspberri Pi). I created a screen to adjust the system time.
If the date & time are set to the future, everything is OK, but if it's set to the past, anything using the tkinter after() method to schedule events never happens. I believe after() works by polling system time, and the scheduled times are now far in the future.
I verified this by setting the time for a minute into the past. Initially, any elements using the after() function stopped updating, but the GUI was still responsive to click events. A minute later, those elements continued to update.
Related
This Question back in 2010 is about the same problem, but has no solutions.
Side Note - the user running the GUI doesn't have privileges to set the time, so it is actually starting a service (which it has the privilege to do), and writing a time string to a FIFO pipe. The service running as root reads the pipe and updates the time. I have verified the time is correctly set with this method.
Update
I never came up with a good way for this to work. So I have a message box to say that application would need to restart after the time change so the user at least knew what was about to happen. If they were OK with that, the application terminated and relaunched itself.
I have a large data acquisition and control program written in Python3.4.2 using GUI mostly developed on Glade 3.18.3, Gtk3.0 GObject running Debian 8 with XFCE.
There are timers that keep doing things, and these work fine. After startup, the program runs for some 3 - 7 days, then suddenly, all of the windows go blank and stay blank. Other applications are not affected. Memory and CPU usage is modest.
There are no indications of problems prior to the windows going blank. The windows show their title bars and respond normally to minimize, restore, move to another Workspace, etc. It looks like they are not getting repainted - no widgets are visible at all. The code is way too large to post here, and I am not able to isolate a specific problem area for lack of obvious symptoms other than the blank screens. There are no error messages or warnings.
The timers continue to run, acquire data and control things. This happens whether the program is run from the command line or under PyDev in Eclipse.
Things I have tried:
In the main timer loop, I put code to look for a file, and then exec the command in it, printing the results, so I have been able to mess with the program in real time:
Replace the usual Gtk.main() with a while loop whose variable, if not made false, will re-execute the Gtk.main(). Executing Gtk.main.quit() stops Gtk.main and starts it again. Windows still blank. Did this repeatedly to no avail.
Experimented with garbage collection with GC. Collecting garbage makes no different. Windows still blank.
Put in code to print percent of time consumed by the timer loops. Fairly steady around 18 - 20% of available CPU time, so nothing is hogging the CPU preventing re-paint.
I have a button that clears a label. I read the label, then executed a builder.get_object(...).activate command to the button. I re-read the label and it was now properly blank. So events and widgets appear to be working normally, at least to some extent.
Finally, if I click on the close X on the title bar, XFCE asks me if I want to wait or close now. So it seems as though there may be a disconnection or problem with signals and the OS, even though XXX.activate() works.
Web searching is in vain. Does anybody have ideas of what might be happening, useful diagnostics, or other suggestions? Many thanks!
April 27, 2017 Update:
I have taken two substantial steps to mostly work around problems. First, partly in response to a couple of Gtk crashes over the last few months, instead of ending the main program with:
Gtk.main()
I end with:
while wannalive:
try:
Gtk.main()
except:
pass
wannalive is True until user does a quit, so recovery is instant.
Second, I grouped all of the code for each window setup and initial population of static items into two functions. I also made another function for closing a window. These functions propagate to children, grandchildren windows. A function in the top window first, closes, then re-creates all windows, with one call. In operation, there are overlaps in what windows exist, but that is not a problem.
Above, I describe that I can inject code with an external program. The external program has a button that injects a call to that third function. In about five seconds or less, the result of a single button click is to replace all blank windows with functional windows. For my purposes in a controlled environment with a trained operator, this is acceptable.
Next, let me address the relationship between the timer loops and GUI events processing. I do use GObject.timeout_add(ms, somefunction). Experiment shows that a button that calls time.sleep(5) stalls the timer. Experiment shows that injecting time.sleep(5) in the timer loop stalls the GUI. This is consistent with my belief (correct me if I am wrong) that Python runs on a single thread. Therefore, bad code caught in an infinite loop should stall both the GUI and the timer loop. (The program has one timeout_add call.)
We have a (very) Legacy application written in VB6 (15 years old?).
The application contains a timer with 300ms interval. The Sub called when the timer ticks executes a batch of code that talks to some SQL servers, prints some labels and so on.
When everything is working OK, this Sub executes in 5ms to 10ms - i.e. before the next timer interval occurs - but it also wastes 290ms before the next tick.
We have a need to make this application a little faster, and one option is to change the interval to 1ms - before we do so, I would just like to confirm whether the timer will abort the interval (aka - completely ignore the tick) if the previous interval is still executing - or will it start building a stack of calls to the sub resulting in a hang after a while? (i am of course assuming all ticks get executed in the same thread as the gui – thus we’ll need to use DoEvents after every tick to ensure the UI doesn’t hang.)
I’ve tried looking into this, but finding reliable information on the old VB6 timers is proving tricky.
We do have this scheduled in to be re-written in .net using threading & background worker threads - this is just a short term fix that we're looking into.
That's not how VB6 timers work, the Tick event can only fire when your program goes idle and stops executing code. The technical term is "pumps the message loop again". DoEvents pumps the message loop. It is a very dangerous function since it doesn't only dispatch timers` Tick events, it dispatches all events. Including the ones that lets the user close your window or start a feature again while it is still busy executing. Don't use DoEvents unless you like to live dangerously or thoroughly understand its consequences.
Your quest to make it 300 times faster is also doomed. For starters, you cannot get a 1 millisecond timer. The clock resolution on Windows isn't nearly high enough. By default it increments 64 times per second. The smallest interval you can get is therefore 16 milliseconds. Secondly, you just can't expect to make slow code arbitrarily faster, not in the least because Tick events don't stack up.
You can ask Windows to increase the clock resolution, it takes a call to timeBeginPeriod(). This is not something you ought to contemplate. If that would actually work, you are bound to get a visit from a pretty crossed dbase admin carrying a blunt instrument when you hit that server every millisecond.
If the timer is a GUI component, (ie. not a thread pool timer), and fired by WM_TIMER 'messages', then the 'OnTimer' events cannot 'stack up'. WM_TIMER is not actually queued to the Windows message queue, it is synthesized when the main thread returns to the message queue AND the timer interval has expired.
When everything is working OK, this Sub executes in 5ms to 10ms - i.e.
before the next timer interval occurs - but it also wastes 290ms
before the next tick.
This is exactly what you have set it up to do if the time interval is 300ms. It is not wasting 290ms, it is waiting until 300ms has elapsed before firing the Tick event again.
If you want it to execute more often, then set the Time interval to 1ms, Stop the timer at the start of the Tick event and start it again when you have finished processing. That way there will only ever be 1ms idle time between operations.
If you put your timer interval faster than your execution time, this lock will probably allow you to execute your code as quickly as you can in VB6.
Private isRunning As Boolean
Private Sub Timer1_Tick()
If Not isRunning Then
isRunning = True
'do stuff
isRunning = False ' make sure this is set even in the event of an exception
End If
End Sub
However, if you are inside this event handler as much as you want to be, or as fast as possible, close to 100% of the time, your application will become slow to respond to or unresponsive to UI events. If you put the DoEvents inside the do stuff you will give the UI a chance to process events, but UI events will halt execution inside do stuff. Imagine moving the window and halting execution... In that case, you probably want to spawn another thread to do the work outside of the UI thread, but good luck doing this in VB6 (I hear it's not impossible).
To maximize speed, with a looping set of instructions, remove the timer all together and have it a function called one at the end of the program entry point (Sub Main or Form_Load).
Within the function, Do a loop and use QueryPerformanceCounter to manage the repeat interval. This way you remove the overhead of the timer message system and can get around the minimal timer interval that exists with the timer.
Add Doevents once at the the top of the Loop so the loop so other events can fire; and consumes idle time while waiting.
There are 2 forms.
Form2 isn't auto-created.
Form2:=TForm2.Create(Application);
Form2.Show;
If to do Sleep(10000); inside any forms then another one will be frozen. How to prevent this behavior?
My problem: a big text file (3 Mb) is continuously assigned (Lines.Assign) into a text editor, so a form is frozen.
Can I use another unfrozen form (not modal) to show a progress bar (a style is pbstMarquee)?
All GUI code should be run from the main thread, and it looks like you are following that rule.
If you call Sleep then the calling thread will not execute code until the timeout elapses. If you call Sleep from the main thread, then the message queue will not be pumped until the timeout elapses. Hence the entire app appears frozen.
Why does calling Sleep from one form affect another form? Because all GUI components are served from the single message queue of the main thread. Once you stop pumping that queue, all GUI components stop receiving queued messages like WM_PAINT, WM_KEYDOWN etc.
As I understand it your problem is that your application appears hung when you are loading a 3MB text file into an edit control. That size of file doesn't sound very large to me and one obvious solution would be to find an edit control that performs the load better. For example I'm pretty sure that Notepad, Notepad++ etc. do not take steps like showing progress when loading such files. I rather suspect that those apps don't pump the queue when loading files but you just don't notice because of the short time taken.
What you don't want to happen is for you to pump your queue to keep your GUI responsive and in turn allow the user to start loading another file whilst the first one is still loading. You need to disable your UI whilst processing a load operation. A modal progress dialog is one way to do that.
If you can't switch to a better performing control, you could show a modal progress dialog and use a background thread like this. The background thread would have load the file in small chunks, say into a string list. After each chunk of the file was ready it would then call Synchronize and get the main thread to add the contents of the string list to the edit control, and then clear the string list. The thread would then continue and load the next chunk. Adding to the edit control in small chunks would allow you to keep the message queue serviced.
You could show progress in a status bar rather than a modal dialog which would be less intrusive. But just remember to disable any UI that would cause re-entrant execution.
Better load your file in a separate thread. Or you will have to create your second form in a plain WinAPI, because VCL doesn't support multithreading.