11.1 Event-Driven Programming, Asynchronous Events, and Concurrency

Key Takeaways

  • In an event-driven program, an event loop waits for events and calls the handler registered for each one, so the order of execution depends on the order of events.
  • To trace event-driven code, apply the handlers one at a time in the order the events occur, carrying shared state from one handler to the next.
  • Asynchronous events can arrive at any time and in any order, causing bugs such as processing a double click twice or using data before a request has finished.
  • A race condition occurs when concurrent code reads and writes shared data and the result depends on timing; two updates to count ← count + 1 can overlap so that one is lost.
  • Fixes include disabling a control while it is being processed, checking state before acting, making updates atomic with locks, and handling events through a queue.
Last updated: September 2026

What this competency asks

ETS asks you to know the concepts of event-driven programs that respond to external events (for example, sensors, messages, and clicks). Beyond tracing, finding inputs for given outputs, describing purpose, and supplying missing code, you should be able to:

  • Identify possible errors due to asynchronous events.
  • Identify aspects of concurrency in event-driven programming.

How event-driven programs work

A traditional program runs from top to bottom. An event-driven program instead waits for events and reacts to them.

PartRole
EventSomething that happens: a click, a key press, a timer tick, a sensor reading, an arriving message
Event handler (callback)The procedure that runs when a particular event occurs
RegistrationConnecting a handler to an event source, such as "when this button is clicked, call onSubmit"
Event loopRuns continuously, takes the next event (often from a queue), and calls its handler

Examples

  • Scratch: when green flag clicked, when this sprite clicked, when I receive [message]
  • JavaScript: button.addEventListener("click", handleClick)
  • A microcontroller: when the motion sensor detects movement, turn on the light
  • A chat app: when a new message arrives, display it

Games, graphical interfaces, web pages, mobile apps, and Internet of Things devices (Section 15.3) are all event-driven.

Tracing event-driven code

Handlers share state through variables. To trace, apply the handlers in the order the events occur.

int count ← 0

void onAddClick ( )
    count ← count + 1
    print count          // print a space after the value
end onAddClick

void onResetClick ( )
    count ← 0
end onResetClick

Events: Add, Add, Reset, Add, Add.

EventHandlercount afterPrinted
AddonAddClick11
AddonAddClick22
ResetonResetClick0—
AddonAddClick11
AddonAddClick22

Output: 1 2 1 2. A different event order gives different output from the same code. That is the defining feature of event-driven programs.

Working backward: to produce the output 1 2 3, the events must be three Add clicks with no Reset between them.

Errors caused by asynchronous events

Events are asynchronous: they can arrive at any time, in any order, and sometimes while other work is still in progress.

ProblemWhat happensTypical fix
Double submissionA user clicks "Pay" twice quickly, and two orders are chargedDisable the button while processing; ignore repeats with a state flag
Using data before it arrivesA handler displays results before a network request finishes, showing empty or old dataUpdate the display in the handler for the "data loaded" event
Unexpected orderA "Stop" event arrives before "Start" has finished setting upCheck the current state in every handler
Event during a long taskThe interface freezes, or events pile upKeep handlers short; move long work to a background task
Stale sensor readingsA value changes between being read and being usedRead once into a local variable, then use that copy
Missed or dropped eventsEvents arrive faster than they can be handledQueue events; limit how often they are sampled

Concurrency

Concurrency means several tasks are in progress during the same period. They may be interleaved on one processor or run truly in parallel on several cores. Event handlers, timers, background downloads, and threads can all run concurrently and share data.

Race conditions

A race condition occurs when the result depends on the unpredictable timing of concurrent operations on shared data. The statement count ← count + 1 is really three steps: read count, add 1, write the result.

TimeTask ATask Bcount in memory
1reads 55
2reads 55
3writes 66
4writes 66

Two increments ran, but count rose by only 1. One update was lost. Run 1,000 increments in each of two tasks, and the total may come out below 2,000, and differently each time.

Preventing concurrency errors

  • Mutual exclusion (locks): only one task at a time may run the code that updates shared data.
  • Atomic operations: use an increment that the system guarantees cannot be interrupted.
  • Avoid shared mutable state: give each task its own data, or pass messages instead of sharing variables.
  • Single-threaded event queues: many interface frameworks run all handlers one at a time on a single thread, which avoids races among handlers but makes long handlers freeze the interface.

Deadlock is another concurrency hazard: two tasks each hold a resource the other needs and wait forever. Acquiring resources in a consistent order prevents it (Section 15.2).

Classroom connection

Block-based environments make event-driven ideas concrete. Two sprites that both respond to "when green flag clicked" run concurrently. Students quickly see that the result can depend on which script runs first, which is a natural first encounter with race conditions.

Test Your Knowledge

A program has two handlers that share int count ← 0. onAddClick adds 1 to count and prints count; onResetClick sets count to 0 and prints nothing. The user clicks Add, Add, Reset, Add. What is printed?

A
B
C
D
Test Your Knowledge

An online store sometimes charges customers twice because they click the "Place order" button twice before the first click finishes processing. Which change best fixes this asynchronous-event problem?

A
B
C
D
Test Your Knowledge

Two concurrent tasks each execute total ← total + 1 one thousand times on a shared variable that starts at 0. The final value is sometimes less than 2,000. What best explains this?

A
B
C
D
Test Your Knowledge

Which statement best describes an event-driven program?

A
B
C
D