Which is what putting most of this stuff on the background accomplishes.
The part you’re missing entirely is the complexity that’s hidden behind the weasel word “most”.
The majority of event handlers from a GUI app do not do anything complex, computationally expensive, or blocking. They do things like setting flags, trigger changes in the UI state (i.e., show/hide/update widgets) bump counters, etc.
No one in their right mind would ever consider going through the trouble of doing this stuff in separate threads/processes. “Most” handlers run perfectly fine on the main thread.
Nevertheless software changes, and today’s onClick handler that sets a flag to true/false tomorrow is required to emit a metric event or switch a different treatment depending on the state of a feature flag or A/B test, or is required to write a setting to disk or something like that.
How do you draw the line in the sand that tells whether this handler should run on the main thread, should trigger a fire-and-forget background task, or should be covered by a dedicated userflow with a complete story board?
That’s the stuff that’s hand-waved away with weasel words like “most”.
This blog post delivers a crisp mental model to tell which approach is suitable: follow the real time computing rulebook, acknowledge that each and every handler has a time budget, and if a handler overspends it’s budget them it needs to be refactored.