Skip to content

This issue was moved to a discussion.

You can continue the conversation there. Go to discussion →

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Closed
dbieber opened this issue Jan 5, 2024 · 0 comments
Closed

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

dbieber opened this issue Jan 5, 2024 · 0 comments

Comments

@dbieber
Copy link

dbieber commented Jan 5, 2024

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.

@Textualize Textualize deleted a comment from github-actions bot Jan 5, 2024
@Textualize Textualize locked and limited conversation to collaborators Jan 5, 2024
@davep davep converted this issue into discussion #3967 Jan 5, 2024

This issue was moved to a discussion.

You can continue the conversation there. Go to discussion →

Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant