Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Chris Miller on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

VFP6 - How Do You Set a NOWAIT Condition on the Default VFP _SYSMENU 3

Status
Not open for further replies.

Booleanist59

Programmer
Apr 8, 2014
15
US
I've inherited a few old applications written in VFP6 from the 90's. The _screen is referenced with no base level form in place, A bitmap background is displayed, and it uses the VFP _SYSMENU by replacing its own menu for _SYSMENU. We noticed a problem with the CPU Utilization rate - there are a lot of these apps running and drawing 25% constant CPU utilization rates even while just sitting idle which is interfering with the users' printer ques. I threw a form together with a pirated hand written menu with a NOWAIT flag and the utilization rate drops to zero.

Is there a way to just set the NOWAIT option on the default VFP _SYSMENU ?

I've been using the menu generator and copying the code from a screen based version into the a form based version with its own menu to ensure that was the reason for the CPU utilization (and it was) but these menus are complicated and tedious to adjust manually once in the form version when changes are required.

Any suggestions or info would be greatly appreciated.

Booleanist59
 
I'd like to thank Olaf, Tamar and Dan for their persistent help through this puzzling design and the hidden CPU Utilization Rate on minimized windows. My former co-worker sounds an awful lot like Dan's old nemesis. This guy wrote like he came off the farm back when FoxPro was running on DOS PCs or early Pre Win 95 windows. Complete lack of structured design. Anybody ever open a report and find fifty name labels piled one on top of the other with a visible condition set based on when the count equals that worker's number? How about letters scanned in as bitmap background files with data elements targeted in the gaps on the letters? Never mind that 550 workers constantly move around the agency or that printer font geometry differs from printer to printer. Anyway - thought you could all use a few laughs.

Again, my thanks to all of you for helping me decipher unfamiliar and forgotten territory behind working from the screen without forms to find that CPU Utilization source.

Regards,

Dave

PS: Tamar, I knew that was probably your name but I didn't know if somebody else might have just used it as their handle - saw an article that the DonaldTrump on Twitter isn't him - he's TheDonaldTrump or something. Anyhow, had to let you know what a gift the VFP Hacker's Guides has been to my work - I've been here 15 yrs as vb programmer but a lot of our legacy code comes from dBase IV Plus coding roots so FoxPro/VFP re-emerged once again. I write a lot of VB apps but the VFP language has changed so many times over this period, I'd never be able to keep it all straight without the Hacker's Guide for reference. Great piece of work - Thanks!
 
Olaf said:
>Activate Menu _Msysmenu is actually a wait state

I didn't know that, but of course the purpose of the genmenu code is to start the menu and also show it, so Activate Menu _Msysmenu is not needed at all and surely not as "cleanup code".
If it's a wait state, then why does it utilize a cpu core to 100%, though? It's used there without the nowait clause. Without testing, I'd rather say the while loop keeps it alive.

You could always test it.

I said it's a wait state, and I also said it shouldn't be used. It's a fragile wait state. It ends when ANY event takes focus from the menu (i.e. Messagebox(), a form running, etc.). That's why the original programmer (I use the term loosely) put in the DO WHILE.

I call it flailing. The programmer didn't know how the product works so they tried everything they could think of and landed on something that "worked" (it kept the application open) but didn't actually "work" (it caused other problems).

I'm dealing with this daily. I routinely find calls to SetFocus() *after* RETURN in Valid() methods. Or Clear Events immediately after Read Events in main programs. (Ummm... no.)

People who don't know the product as well as we do can be inventive. (I'm being kind again.)
 
Yes, I could test it, I will. But genmenu produces code starting the menu when you do menu.mpr, and that includes activate menu, doesn't it? And is it needed twice, for a screen or form menu? The menu would only "end", if a context menu, wouldn't it? Maybe I need to do more experiments...

Bye, Olaf.
 
Thanks, Tamar.

So a) there is a wait state, if not using the NOWAIT clause, but b) the menu doesn't vanish, when using it, so the while loop mainly was there to react to "ON SELECTION BAR 2 OF file m.insystem = .f.", which was the way to exit from the application. @Dave: That is the ON SELECTION definition of the Exit menu item, you need to change that to QUIT or CLEAR EVENTS.

Bye, Olaf.
 
CLEAR EVENTS would be the preferred way.

I'm a little bit opposed to sticking QUIT in the middle of apps (well, a LOT opposed) because the application's cleanup code doesn't execute.

The only thing worse would be calling the Windows ExitProcess API function. (Basically, CTRL-ALT-DEL and kill the task from task manager but doing it through code.) I'm cleaning up an app now that does that as the last line of the error handler.

"End of File Encountered" --> KILL IT DEAD! Ugh!
 
The only thing worse would be calling the Windows ExitProcess API function. (Basically, CTRL-ALT-DEL and kill the task from task manager but doing it through code.) I'm cleaning up an app now that does that as the last line of the error handler.

Hey, maybe I wrote that app <g>.

Seriously, I do use ExitProcess as the last line of my error handler. Dan, I understand why you would consider that the eighth deadly sin. Most VFP folk would agree with you. I only do it in a very controlled way, after rolling back all transactions, reverting all buffers, etc.

The problem with an error handler is that if you try to close the application by normal means (either by QUIT or by going through the normal shutdown process), you will have to do a lot of stuff that is unrelated to the error. For example, you will have to close any open forms, and these might have code in their Destroy or QueryUnload which includes user prompts (for dealing with unsaved data, say). Or the entire application might have shutdown code that asks the user to confirm that they really want to shut down.

The point is that those actions can interfere with the shut down , and even prevent it from happening. The result is that the application continues to run, despite the fact that an error condition is in force. That is highly undesirable. That's why I use ExitProcess. But I stress I only do it in those very narrow circumstances.

Sorry if this is slightly off topic, but I hope it will be of some interest. I've seen too many problems caused by error handlers failing to close the application.

Mike


__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro articles, tips and downloads
 
It's untrue QUIT doesn't cause cleanup code.

If you QUIT, all unload/destroy events run and if you clean up the oop way you clean up.
What you can't do with QUIT is put cleanup code after READ EVENTS. But you can do cleanup in the destroy event of your application class.

Code:
Public goApp
goApp = CreateObject("myapp")
On Shutdown Quit
Read Events

Define Class myapp as custom
   Procedure Destroy()
      MessageBox("Bye")
      * clean up here, perhaps!?
   Endproc
EndDefine
Is it somewhat unelegant to have READ EVENTS without CLEAR EVENTS? Yes. I said CLEAR EVENTS or QUIT, it's your decision. But QUIT does force the exit more than CLEAR EVENTS. If you do ON SHUTDOWN CLEAR EVENTS, and run that in the IDE, that won't quit foxpro, if you use the close button of the _screen.

Bye, Olaf.

 
After testing, the best way to isolate this menu problem (in these apps) was to place the READ EVENTS in the Cleanup code section on the menu (which was a misleading term for the section as you pointed out) in place of the DO WHILE loop to alleviate the loop running endlessly ("flailing") and pegging the CPU Utilization rate whenever the screen lost focus or was minimized. I used the Exit menu pad to call a procedure to set the m.insystem condition to .f. and issue the CLEAR EVENTS to return control to the original prg. Once that calling prg evaluates and exits based on the m.insystem value, I was able to insert some additional cleanup code and safeguards before utilizing the ON SHUTDOWN procedures via the QUIT. That also cleared up a secondary problem with users not properly exiting the system so I can now get exclusive locks on the tables when I have to trip the timer condition to force users off the system for maintenance or emergencies.

Regards,

Dave
 
Mike Lewis said:
Seriously, I do use ExitProcess as the last line of my error handler. Dan, I understand why you would consider that the eighth deadly sin. Most VFP folk would agree with you. I only do it in a very controlled way, after rolling back all transactions, reverting all buffers, etc.

Oh, I don't mind when it's done in a controlled way and for proper reason.

But, um, any trivial error that probably SHOULD be ignored isn't a good reason to throw a hard shutdown. Not all errors mean "Everyone out of the pool!". Except in this app. In this app it's sort of like

Code:
Try
   do something
Catch
   KILL IT DEAD!
Endtry
 
Booleanist59 said:
After testing, the best way to isolate this menu problem (in these apps) was

I'm so glad you found a good resolution!

I know all too well how hard it is to deal with WTF* code.

Dan

*What's this for?
 
> the best way to isolate this menu problem (in these apps) was to place the READ EVENTS in the Cleanup code section on the menu

Well, it's arguable, but I'd rather put READ EVENTS in main.prg

That's where it belongs, perhaps it can be inside a Method of an application class, where you can return to from error handling via RETURN TO goApp.Readeventsmethod, but not in the code of a menu.
The menu MPR should build the menu, show it and exit.

Again, it's arguable, for one reason, as you have CLEAR EVENTS in the menu, too. Technically it makes no difference. It would be wrong, if it's in a main form init, for example, as it would make it impossible for the form to show. But for the same reason I'd not put it into the mpr code, neither manually nor via the menu designer, it's hindering the return from the MPR code, which should just set up and start the menu. It's a mater of taste.

Bye, Olaf.

 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top