I’ve never particularly liked the idea of OnUpdate events. They have always seemed kind of inelegant to me, but I haven’t talked about it much since I don’t really have a compelling argument against them, save for "bad smells." Today, though, I was using RAD Studio and saw an access violation error in the IDE. This was immediately followed by the following error, which repeated over and over again. The stack dump tells the story:
[20A635EB]{coreide100.bpl} DocModul.AnyModuleModified (Line 3466, "DocModul.pas" + 10) + $41
[20A635E5]{coreide100.bpl} DocModul.AnyModuleModified (Line 3466, "DocModul.pas" + 10) + $3B
[00419D8B]{bds.exe} AppMain.TAppBuilder.FileSaveAllActionUpdate (Line 4067, "ui\AppMain.pas" + 1) + $0
[200401A7]{rtl100.bpl } Classes.TBasicAction.SetOnExecute (Line 11109, "common\Classes.pas" + 9) + $9
[201513B1]{vcl100.bpl } Forms..TScrollBox + $231
[2004009D]{rtl100.bpl } Classes.TBasicAction.Destroy (Line 11048, "common\Classes.pas" + 2) + $5
[2013D8C7]{vcl100.bpl } Controls.TControl.ScaleConstraints (Line 4033, "Controls.pas" + 12) + $7
[2015E854]{vcl100.bpl } Forms.DoPosition (Line 6778, "Forms.pas" + 44) + $2
[2015E86E]{vcl100.bpl } Forms.DoPosition (Line 6778, "Forms.pas" + 44) + $1C
[2015E8DC]{vcl100.bpl } Forms.DoAlign (Line 6795, "Forms.pas" + 0) + $4
[201631AA]{vcl100.bpl } Clipbrd.TClipboard.AssignPicture (Line 386, "Clipbrd.pas" + 7) + $14
[201632F9]{vcl100.bpl } Clipbrd.TClipboard.SetAsHandle (Line 430, "Clipbrd.pas" + 0) + $9
[20162637]{vcl100.bpl } Forms.TCustomFormHelper.WriteGlassFrameBottom (Line 8945, "Forms.pas" + 2) + $0
[2016291F]{vcl100.bpl } Forms.TApplicationHelper.GetEnumAllWindowsOnActivateHint (Line 9087, "Forms.pas" + 0) + $3
[0042297A]{bds.exe } bds.bds (Line 195, "" + 7) + $7
Note the line in bold. Because this is an OnUpdate event, it’s going to repeat forever. The user is trapped. There is no chance to save your work, or to exit the IDE normally. You have to end task. Sure, this is a secondary error; it’s almost certainly the consequence of the preceding access violation, rather than a defect in the OnUpdate event itself. But because that event is not robust enough to handle the consequences of the previous error, the user is trapped.
My conclusion is that OnUpdate event handlers are dangerous if they do not detect anything that could possibly go wrong with the references they use, and exit gracefully in that case.
{ 4 } Comments
Why single OnUpdate out for this…. Many things suffer the same problem…
OnPaint
OnMouseMove (in general, its impossible to get out of this without moving the mouse and triggering the A/V)
OnUpdate is usually smarter than the help makes them seem to be. For instance, onUpdate of actions attached to menu items are only triggered if the menu items are visible.
Even you do not use OnUpdate, it will consume your CPU usage.
http://stanleyxu2005.blogspot.com/2008/01/performance-issue-of-taction.html
2 cents:
if you want to simulate radiobuttons behavior with menu items, then you will have to use OnUpdate handlers for actions linked to that items. this is because AutoCheck, Checked and GroupIndex properties are not synchronized between themselves (I mean all at the same time). Thus you may have situation when user selects one menu item twice and all items are unchecked. there is no elegant way of controlling that (smth. like AllowAllUp property would be very appreciated). the only way is to write OnUpdate handlers.
I somewhat share your concern for OnUpdate events and they have annoyed me within the Delphi IDE when they go wrong - they are however very convenient. An OnUpdate event with a couple lines of code that enables or disables a button(s) can replace a whole bunch of annoying code that needs to be called from numerous places. In this they are a great way of simplifying code, however when they do go wrong it can be very nasty.
Post a Comment