There are many ways to manage concurrency concepts: with threads, coroutines, continuations, generators, ... and events. A page on Event programming and why it is relevant to Tcl/Tk programming explains some of the background behind Tcl's emphasis of the latter.
Events are a relatively "safe" programming model, particularly when compared to threading. John Ousterhout's influential "Why Threads Are A Bad Idea" is available as PowerPoint slides [L1 ] or in a PDF [L2 ].
Notice that C# makes events first-class objects. This is consistent with Anders Hejlsberg's earlier work with Delphi ...
Steve Ferg created a SourceForge placeholder [L3 ] for event-driven material, including his "Event-Driven Programming: Introduction, Tutorial, History".
This Wiki has several other pages [L4 ] on event-oriented programming techniques.
Martin Lemburg July 11nd, 2002: I have a question:
Why isn't there an event Invoke for invokeable widgets, like buttons? Wouldn't make it sense to have such an event? To bind widgets using the Invoke event, like to connect a widget with the -command option to an event handler?
Then ...
button .b -text exit -command {cmdProc .b [clock seconds]};
... would be equal to ...
bind .b <Invoke> {cmdProc %W %t};
It shouldn't be a problem to use the substitution capabilities during the usage of a binding, like:
button .b -text exit -command {cmdProc %W %t};
Wouldn't that be nice and consequent? Wouldn't it be consequent (for example) to use bindings to scrollbars or entries too? ...
entry .e -textvariable filter; button .b -text "filter"; listbox .lb -listvar data -selectmode extended; scrollbar .sbx -orient horizontal; scrollbar .sby -orient vertical; bind .e <Validate> {validateFilter %V %s}; bind .b <Invoke> {filter .e .lb}; bind .lb <XScroll> {.sbx set}; bind .lb <YScroll> {.sby set}; bind .sbx <Invoke> {.lb xview}; bind .sby <Invoke> {.lb yview};
There would be the chance to elimate all (event)handlers from that code, that only builds up the GUI. The code to handle events could use now use bindings.
While Tcl-ers are generally trained to believe, "event orientation: good; threads: bad", that is, of course, an exceptionally truncated version of reality. Threading's programmability problems begin with the necessity to mess with data consistency. Event-based programming, on the other hand, needs continuations or closures or comparable expressive power to manage the program-control stack. With none of these, developers must mess with stack contents on their own, and, of course, that's a horror.
WK Threads used for everything are a bad thing. I think that Tcl community is getting to like threads, but I like the idea that I can have every single interaction (GUI and network) in one thread and if I need some long lasting calculations, I can just add a thread and communicate with it using thread::send -async, and then (well a small nice wrapper is a must here :-) I can talk to a thread similar to a networked application. And it takes 30 lines to wrap this:
set code [catch $someCommandList result] myCallback $code $result
into
asyncEval $someCommandList myCallback
And this is how larger calculations could be done easily.
Tcl performs its usual compromise and provides everything as a string. More precisely, Tcl gives enough introspection to pack and unpack events and their "formal arguments". That's enough.