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 Mike Lewis on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

tkwait - why it chokes when variable is global 2

Status
Not open for further replies.

smugindividual

Programmer
Apr 14, 2003
104
0
0
US
Does anyone know why tkwait variable is flakey when monitoring a global variable?

I launch a pick list when the user right clicks on a tag. The code waits for a variable that is set when the user either selects an item from the list or closes the list without selecting anything(variable gets unset).

If a pick list is already on the screen and the user right clicks another tag the code destroys the first and unsets the variable being waited on, except tkwait never sees the variable being unset. If the user keeps right clicking and opening new pick lists the code will keep getting stuckon the tkwait. When the user selects an item or cleses the list without selecting an item, all the waits come back at once.

Problem is slao noted when the pick list is up and user exits the application. Exit routine unsets the variable if it exists, but tkwait doesnt ever see it.

The variable is declared global everywhere it needs to be.

Please help
 
The following code is the easiest example of the problem i am seeing.

proc mymain { } {

toplevel .top
frame .top.f
button .top.f.button -text "click" -command "myfunc"
pack .top.f.button
pack .top.f
}

proc myfunc { } {
global waitvar

set waitvar ""
myfunc2
puts "waiting"
tkwait variable waitvar
puts "done waiting"
}

proc myfunc2 { } {
global waitvar

if { [winfo exists .bla] } {
puts "window exists so we will unset the waitvar to trigger the tkwait"
unset waitvar
set waitvar ""
destroy .bla
}

toplevel .bla
frame .bla.f
button .bla.f.but -text "to exit" -command "catch {unset waitvar} ; destroy .bla"
pack .bla.f.but
pack .bla.f
}


 
Do you see the same thing with "vwait"?

Bob Rashkin
rrashkin@csc.com
 
The code you posted confirmed my original suspicion: you inadvertently created nested event loops. How? Let's go through the code step-by-step as the user clicks on the "click" button twice in a row, before clicking the "to exit" button:[ol][li]User clicks "click"[/li]
[ol][li]myfunc calls myfunc2[/li]
[li]myfunc2 creates "to exit" window[/li]
[li]myfunc calls tkwait, starting a nested instance of the event loop that cannot return until it detects waitvar being set/unset[/li][/ol]
[li]User clicks "click"[/li]
[ol][li]myfunc calls myfunc2[/li]
[li]myfunc2 unsets/sets waitvar[/li]
[li]myfunc2 deletes old "to exit" window[/li]
[li]myfunc2 creates new "to exit" window[/li]
[li]myfunc calls tkwait, starting a second nested instance of the event loop that cannot return until it detects waitvar being set/unset[/li][/ol][/ol]At this point, because the event handler invoked by the second click on the "click" button hasn't completed execution, the first nested event loop is "on hold" and unable to detect that waitvar was unset/set. The second nested event loop doesn't return yet, because the unset/set of waitvar occurred before it was invoked.

When the user finally clicks the "to exit" button after the above actions, we get the following sequence:[ol][li]event handler unsets waitvar[/li]
[li]event handler destroys [tt].blah[/tt] window[/li]
[li]event handler returns to second nested event loop[/li]
[li]second nested event loops detects waitvar unset and terminates[/li]
[li]event handler (myfunc) invoked by second click on "click" prints "done waiting"[/li]
[li]event handler invoked by second click finally terminates, returning to first nested event loop[/li]
[li]first nested event loops detects waitvar unset and terminates[/li]
[li]event handler (myfunc) invoked by first click on "click" prints "done waiting"[/li]
[li]event handler invoked by first click finally terminates, returning to original ("primary") event loop[/li][/ol]As for a solution, well that depends on exactly what you're trying to do. I'm not sure exactly what you mean by a "pick list" in your original message. Perhaps a popup menu would be appropriate, in which case, read the documentation for the tk_popup command; from the Tcl'ers Wiki ( go to the "popup" page,
- Ken Jones, President, ken@avia-training.com
Avia Training and Consulting, 866-TCL-HELP (866-825-4357) US Toll free
415-643-8692 Voice
415-643-8697 Fax
 
Thanks Ken,

I'll take a look at the tk_popup and hopefully it help me out. I guess it'll be a good thing to remember that these wait events work like a first-in last-out stack.


Thanks again



 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top