多线程 python 应用程序在运行其线程时挂起

发布于 2024-08-17 00:47:59 字数 2204 浏览 8 评论 0原文

我正在尝试创建一个可作为 DBus 服务使用的 MainObject。该 MainObject 应始终保持对其他对象/进程的响应,并且即使在处理其项目时也是非阻塞的。因此,项目会在单独的线程中一个接一个地处理(队列式)。您可以通过 DBus 或 CommandLine 将项目添加到 MainObject。我简化了示例(没有 dbus,没有命令行)来显示我的问题。

我的问题是,如果我重新启用“tt.join()”,应用程序将按预期工作,但它会阻止其他进程。难怪,tt.join 使应用程序等待,直到单独的线程完成其工作。另一方面,如果“tt.join()”保持禁用状态,应用程序不会阻止外部 dbus 事件,但永远不会出现“ThreadTest 完成!” (查看实际输出)

我想要的是我的预期输出,但应用程序应该保持响应。

#!/usr/bin/python2.5

import gobject
import threading
import re
import time

class ThreadTest(threading.Thread):

  def __init__(self):
    threading.Thread.__init__ (self)    
    print '  ThreadTest created!'

  def run(self):
    print '  ThreadTest running ...'
    time.sleep(1)
    print '  ThreadTest done!'
    return True

class MainObject():
  def __init__(self):
    self.timer = gobject.timeout_add(1000, self.update)
    self.loop  = gobject.MainLoop()
    print 'MainObject created!'

  def update(self):
    print 'MainObject updating ...'
    if self.check_running() == False:
      tt = ThreadTest()
      tt.start()
      #tt.join()
    return True

  def check_running(self):
    running = False
    expr = re.compile('ThreadTest')
    for threadstr in threading.enumerate():
      matches = expr.findall(str(threadstr))
      if matches:
        running = True
    return running  


mo = MainObject()
mo.loop.run()

预期产出:

MainObject created!
MainObject updating ...
  ThreadTest created!
  ThreadTest running ...
  ThreadTest done!
MainObject updating ...
  ThreadTest created!
  ThreadTest running ...
  ThreadTest done!
MainObject updating ...
  ThreadTest created!
  ThreadTest running ...
  ThreadTest done!
MainObject updating ...
  ThreadTest created!
  ThreadTest running ...
  ThreadTest done!
MainObject updating ...
  ThreadTest created!
  ThreadTest running ...
  ThreadTest done!

实际产出:

MainObject created!
MainObject updating ...
  ThreadTest created!
  ThreadTest running ...
MainObject updating ...
MainObject updating ...
MainObject updating ...
MainObject updating ...
MainObject updating ...
MainObject updating ...
MainObject updating ...
MainObject updating ...
MainObject updating ...

I am trying to create a MainObject which is availible as a DBus service. This MainObject should always stay responsive to other objects/processes and for this non-blocking even while processing its items. for that reason items are processed in a seperate thread one after another (queue-style). You can add items to the MainObject via DBus or CommandLine. I simplified the sample (no dbus, no commandline) to show my problem.

My problem is, that if i reenable 'tt.join()' the application works as expected, but it is blocking to other processes. No wonder, tt.join makes the application wait until the seperate Thread has finished its work. On the other hand, if 'tt.join()' stays disabled, the application does not block to external dbus events, but never comes to 'ThreadTest done!' (look at real output)

What i want is, my expected output but the applications should stay responsive.

#!/usr/bin/python2.5

import gobject
import threading
import re
import time

class ThreadTest(threading.Thread):

  def __init__(self):
    threading.Thread.__init__ (self)    
    print '  ThreadTest created!'

  def run(self):
    print '  ThreadTest running ...'
    time.sleep(1)
    print '  ThreadTest done!'
    return True

class MainObject():
  def __init__(self):
    self.timer = gobject.timeout_add(1000, self.update)
    self.loop  = gobject.MainLoop()
    print 'MainObject created!'

  def update(self):
    print 'MainObject updating ...'
    if self.check_running() == False:
      tt = ThreadTest()
      tt.start()
      #tt.join()
    return True

  def check_running(self):
    running = False
    expr = re.compile('ThreadTest')
    for threadstr in threading.enumerate():
      matches = expr.findall(str(threadstr))
      if matches:
        running = True
    return running  


mo = MainObject()
mo.loop.run()

expected output:

MainObject created!
MainObject updating ...
  ThreadTest created!
  ThreadTest running ...
  ThreadTest done!
MainObject updating ...
  ThreadTest created!
  ThreadTest running ...
  ThreadTest done!
MainObject updating ...
  ThreadTest created!
  ThreadTest running ...
  ThreadTest done!
MainObject updating ...
  ThreadTest created!
  ThreadTest running ...
  ThreadTest done!
MainObject updating ...
  ThreadTest created!
  ThreadTest running ...
  ThreadTest done!

real output:

MainObject created!
MainObject updating ...
  ThreadTest created!
  ThreadTest running ...
MainObject updating ...
MainObject updating ...
MainObject updating ...
MainObject updating ...
MainObject updating ...
MainObject updating ...
MainObject updating ...
MainObject updating ...
MainObject updating ...

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

趁微风不噪 2024-08-24 00:48:00

默认情况下,gobject 绑定不支持多线程。请在导入 gobject 后尝试执行以下操作:

gobject.threads_init()

The gobject bindings by default aren't multithread-aware. Please try to do the following just after you have imported gobject:

gobject.threads_init()
拥抱影子 2024-08-24 00:48:00

python 中的线程可能是一个陷阱——实际上,这是一个悬而未决的问题。
主要问题是 GIL——Python 的全局解释器锁。

他们发明的克服这个问题的方法之一是“多处理”模块(Python 2.6 中的新功能)——它保留了“线程”接口,但实际上在单独的进程中运行代码:
您可以尝试用多处理来替换 htreading - 但是:在主“线程”上执行所有 dbus 交互、GUI 等 - (即单个进程) - 并与子进程(字符串、列表、字典等)...那会很好用。

另外,我不明白为什么所有这些正则表达式 Voodo 只是为了检查给定的字符串是否存在于 threading.enumerate 的返回值上?
Python 甚至有“in”运算符(因此您甚至不必使用 str 的索引或查找方法):

您可以将整个 check_running 方法替换为:

def check_running(self):
    return 'ThreadTest' in str(threading.enumerate())

Threads in python can be a trap -- it is an open problem, actually.
The main problem is the GIL - Python's Global Interpreter Lock.

One of the ways they invented to overcome this is the "multiprocessing" module (new in python 2.6) - it preserves the "threading" interface, but actually runs the code in a separate process:
You could try jsut replacing htreading by multiprocessing -- but: do all the dbus interaction, GUI, etc.. on a main "thread" - (i.e. a single process) - and trade data with the sub-proccesses (strings, lists, dictionaries, etc)... that would work fine.

Also, I can't figure out why all this regexp Voodo just to check if a given string is present on the return value of threading.enumerate??
Python has even the "in" operator (so you don't even have to use the str's index, or find methods):

you can replace that entire check_running method for:

def check_running(self):
    return 'ThreadTest' in str(threading.enumerate())
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文