## 5.6 More on Actions: Listeners

In previous sections we used procedures or pairs of object and message as actions. Each time an action is invoked, a new thread is created. While this is fine as it comes to efficiency (threads in Oz are light weight), it may cause trouble in that the order in which actions are invoked might be lost: the threads are created in the right order but there is no guarantee that they will run in that order.

The class `Tk.listener` fixes this. An instance of a subclass of `Tk.listener` has a thread of its own in which it serves action messages in order of invocation. For example, in

  `L ={New class $ from Tk.listener
  meth b1 {Browse b1} end
  meth b2 {Browse b2} end
  end tkInit}
  B1={New Tk.button tkInit(parent:W text:'One' action: L#b1)}
  B2={New Tk.button tkInit(parent:W text:'Two' action: L#b2)}
  {Tk.send pack(B1 B2 side:left)}`

the methods `b1` and `b2` are always executed in the same order in which the corresponding buttons are pressed.

When the `tkInit` method of the class `Tk.listener` is executed, a new thread together with a message stream is created. Whenever an action is invoked, where the object `O` of an object message pair `O``#``M` is an instance of `Tk.listener`, no new thread is created but `M` is appended at the end of the message stream. The thread then serves the message `M` as soon as all previous messages on the stream have been served completely. It serves `M` by executing the object application `{``O``` `M``}`.

An additional message `M` to be served can be given to a listener by the method `tkServe`. For example, by

  `{L tkServe(b1)}`

the message `b1` is served by `L`.