Skip to content

long-running thread worker doesn't exit when app is quit #3966

Closed
@dbieber

Description

@dbieber

In the following ExampleApp, I would expect that when the app is quit, the thread worker would terminate too. It does not, and instead the process runs forever.
When I saw that the thread worker does not terminate, my initial thought was perhaps textual failed to set the thread as a daemon, and that this would be an easy fix.

Here's the example code. It continues running even after quitting the app with ctrl-C.

import time
from textual import work
from textual.app import App
from textual.app import ComposeResult
from textual.messages import Message
from textual.widget import Widget
from textual.widgets import Log


class ExampleWidget(Widget):

  class Changed(Message):
    def __init__(self, name: str):
      super().__init__()
      self.name = name

  def on_mount(self):
    self.start_worker()

  @work(thread=True)
  def start_worker(self) -> None:
    while True:
      time.sleep(1)
      self.post_message(self.Changed("And again..."))


class ExampleApp(App):

  def compose(self) -> ComposeResult:
    yield Log()
    yield ExampleWidget()


if __name__ == "__main__":
  app = ExampleApp()
  app.run()

Surprisingly (to me) if I try to minimize the example further, then it starts working as intended and the bug goes away. In the following code, the app successfully quits on ctrl-C. The difference is that the thread worker is in the App rather than in a widget.

import time
from textual import work
from textual.app import App
from textual.app import ComposeResult
from textual.widgets import Log


class ExampleApp(App):

  def compose(self) -> ComposeResult:
    yield Log()

  def on_mount(self):
    self.start_worker()

  @work(thread=True)
  def start_worker(self):
    log = self.query_one(Log)
    while True:
      log.write_line("And again...")
      time.sleep(1)


if __name__ == "__main__":
  app = ExampleApp()
  app.run()

I did notice that in #2593 @davep notes that long-running thread workers are a bad idea. I haven't looked into alternatives yet. If you have a recommendation or rationale, do let me know.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions