说我有一个产生线程的类:
import threading
class SomeClass(threading.Thread):
def __init__(self):
threading.Thread.__init__(self)
def run(self):
while True:
pass
def doSomething(self):
pass
def doSomethingElse(self):
pass
我想要
someClass = SomeClass()
someClass.start()
someClass.doSomething()
someClass.doSomethingElse()
someClass.doSomething()
我怎样才能做到这一点?我知道我可以在函数内部调用一个函数run()
,但这不是我想要的。
您不能直接做您想做的事。后台线程正在运行其run
功能,该功能将永远循环下去,因此它可能无能为力。
当然,您可以在自己的线程上调用该类的方法,但这大概不是您想要的。
Qt,.NET或Cocoa之类的框架之所以可以提供runOnOtherThread
-type方法,是因为每个线程都运行一个“事件循环”,因此它们真正要做的就是发布一个事件。如果将run
方法重写为事件循环,则可以自己执行。例如:
import queue
import threading
class SomeClass(threading.Thread):
def __init__(self, q, loop_time = 1.0/60):
self.q = q
self.timeout = loop_time
super(SomeClass, self).__init__()
def onThread(self, function, *args, **kwargs):
self.q.put((function, args, kwargs))
def run(self):
while True:
try:
function, args, kwargs = self.q.get(timeout=self.timeout)
function(*args, **kwargs)
except queue.Empty:
self.idle()
def idle(self):
# put the code you would have put in the `run` loop here
def doSomething(self):
pass
def doSomethingElse(self):
pass
现在,您可以执行以下操作:
someClass = SomeClass()
someClass.start()
someClass.onThread(someClass.doSomething)
someClass.onThread(someClass.doSomethingElse)
someClass.onThread(someClass.doSomething)
如果您想稍微简化调用接口,以类中更多代码为代价,则可以添加如下包装方法:
def _doSomething(self):
# put the real code here
def doSomething(self):
self.onThread(self._doSomething)
但是,除非您的idle
方法有工作要做,否则您实际上实际上是在这里构建等效于单线程线程池的方法,并且比从头开始构建它要容易得多。例如,使用futures
关闭PyPI的模块(Python
3concurrent.futures
模块的反向端口):
import futures
class SomeClass(object):
def doSomething(self):
pass
def doSomethingElse(self):
pass
someClass = SomeClass()
with futures.ThreadPoolExecutor(1) as executor:
executor.submit(someClass.doSomething)
executor.submit(someClass.doSomethingElse)
executor.submit(someClass.doSomething)
或者,仅使用stdlib:
from multiprocessing import dummy as multithreading
class SomeClass(object):
def doSomething(self):
pass
def doSomethingElse(self):
pass
someClass = SomeClass()
pool = multithreading.Pool(1)
pool.apply(someClass.doSomething)
pool.apply(someClass.doSomethingElse)
pool.apply(someClass.doSomething)
pool.close()
pool.join()
池还有其他一些优势,执行者甚至更多。例如,如果方法返回值,并且您想要启动两个函数,然后等待结果,然后使用前两个结果启动第三个函数,该怎么办?简单:
with futures.ThreadPoolExecutor(1) as executor:
f1 = executor.submit(someClass.doSomething)
f2 = executor.submit(someClass.doSomethingElse)
futures.wait((f1, f2))
f3 = executor.submit(someClass.doSomethingElser, f1.result(), f2.result())
result = f3.result()
即使您稍后切换到4个线程的池,因此f1
并且f2
可能正在同时等待f2
甚至可能首先返回,也可以确保在doSomethingElser
两个线程都完成后立即开始。
这里还有另一种可能性。您是否真的需要代码在该线程中运行,还是只需要它来修改线程所依赖的变量?如果是后者,则只需同步访问变量即可。例如:
class SomeClass(threading.Thread):
def __init__(self):
self.things_lock = threading.Lock()
self.things = []
while True:
with self.lock:
things = self.things[:]
for thing in things:
# pass
def doSomething(self):
with self.lock:
self.things.append(0)
someClass = SomeClass()
someClass.start()
someClass.doSomething()
在这里位于主线程上并没有什么神奇的。如果除了需要修改SomeClass
依赖于变量的变量之外,如果您还想启动doSomething
主线程,以便除了完成任务之外还可以做其他重要的事情,那么可以创建一个短暂的额外线程来doSomething
:
someClass = SomeClass()
someClass.start()
somethingThread = threading.Thread(target=someClass.doSomething)
somethingThread.start()
doOtherImportantStuffWithSomethingIsHappening()
somethingThread.join()
我在让机器人上网时遇到了一些困难。当我运行文件时,bot在我需要的服务器上不在线。在使用pycharm之前,由于计算机上的许多错误,我迁移到了VSCode。在pycharm中,它正常工作,但现在在VSCode中,我无法使它工作。有人能帮我吗? 变量token和canal_id在我的代码中正确配置,我已经在discord上检查了我的应用程序。 代码:
问题内容: 我有一个正在运行的线程,但是从外面我无法绕过一个值来停止该线程。如何在内部发送false / true值或调用运行线程的公共方法?当我按下按钮1?例如: 或 跟进(校对): 问题答案: 如果您通过类而不是通过a定义它,则可以调用实例方法。 还要注意,由于多个内核具有自己的关联内存,因此您需要警告处理器该状态可能在另一个处理器上更改,并且它需要监视该更改。听起来很复杂,但只需将’vola
问题内容: 我有一个在我的应用程序中的单独线程中运行的类。我可以一次运行多个线程,并且这些线程是守护程序。一段时间后, 其中一些 线程需要接收和处理消息。我该怎么做呢? 我的代码示例如下所示: 输出: 但是,我希望最后五行与无关,而不是,我希望对我来说像这样: 我如何正确地向正在运行的线程发送这样的消息? 附录: 如果我在该块之后有这个块,并使用@dano的代码来解决上述问题,则它似乎没有响应这些
我是Java初学者。我想在运行的Java线程对象中调用一个方法。它总是引发以下异常: 线程“AWT-EventQueue-0”java中出现异常。lang.NullPointerException:无法调用“Graphic\u handler.next()”,因为“this.this$0.grap”为null (代码已简化) 下面是我调用该方法的代码部分: 我试图在这里调用方法Next()和las
问题内容: 我有一个在Linux上运行的Python(3)脚本,称为主脚本,该脚本必须从专有DLL调用例程。到目前为止,我已经使用Wine使用以下结构解决了这个问题: 脚本 dll_call.py 由Wine下安装的Windows Python(3)解释器执行。它将返回值转储到一个文件中,然后由等待的主脚本拾取该文件。如果我必须连续执行几次,它不是完全可靠且令人痛苦的缓慢。 我想一次启动脚本 dl
问题内容: 我有一个处理来自.NET Remoting的异步回调的Python脚本。这些回调在虚拟(工作)线程中执行。从我的回调处理程序内部,我需要调用在脚本中定义的函数,但需要在主线程中执行该函数。 主线程是将命令发送到服务器的远程客户端。其中一些命令会导致异步回调。 基本上,我需要等效于.NET的Invoke方法。这可能吗? 问题答案: 您想使用Queue(现在是python 3的队列)类来设
部署0.9.5版本的storm集群 streamparse最新稳定版是基于0.9.5版本的storm的,所以我们需要把storm集群的版本回退到0.9.5,方法如下: wget http://apache.fayea.com/storm/apache-storm-0.9.5/apache-storm-0.9.5.tar.gz 解压后修改conf/storm.yaml文件,添加如下配置项: st
QUUKUS版本2.1.2.最终的 在quarkusDev中运行时,一切都在正确的线程(vert.x-worker-thread-x)中运行,甚至遵守属性,如我所料。 当运行从构建任务构建的quokus-app时,我看到执行线程为(执行器-线程-x)。 不确定为什么执行线程在运行应用程序时发生变化,而不是在quakusDev中运行。顺便说一句,我使用了完全相同的属性,无论是夸克开发和运行构建任务的