我正在尝试在多线程程序中从子线程向主线程发送信号(不能使用多进程)。不幸的是,即使在用尽了所有在线阅读材料(我可以找到)之后,我仍无法清楚地知道如何做到这一点。我是信号和Python的初学者,所以请耐心听我解释,就像向新手解释一样。 我无法在进程中使用 join 方法,因为我希望两个线程同时运行。 这是我发现与此处主题相关的代码 - http://pymotw.com/2/signal/#signals-and-threads 而且它对我来说真的不起作用。
import signal
import threading
import os
import time
def signal_handler(num, stack):
print 'Received signal %d in %s' % (num, threading.currentThread())
signal.signal(signal.SIGUSR1, signal_handler)
def wait_for_signal():
print 'Waiting for signal in', threading.currentThread()
signal.pause()
print 'Done waiting'
# Start a thread that will not receive the signal
receiver = threading.Thread(target=wait_for_signal, name='receiver')
receiver.start()
time.sleep(0.1)
def send_signal():
print 'Sending signal in', threading.currentThread()
os.kill(os.getpid(), signal.SIGUSR1)
sender = threading.Thread(target=send_signal, name='sender')
sender.start()
sender.join()
# Wait for the thread to see the signal (not going to happen!)
print 'Waiting for', receiver
signal.alarm(2)
receiver.join()
如果可能,请用多线程示例进行解释。 预先感谢!
信号和线程真的、真的不能很好地结合在一起。
考虑使用
Event
或其他同步机制。 以下示例创建一个“事件”对象,然后将其传递给两个线程。 一个等待两秒钟,然后示意另一个打印一条消息,然后退出。
import threading, time
def flagger_thread(event):
"""
wait for two seconds, then make 'event' fire
"""
time.sleep(2)
event.set()
def waiter_thread(event):
print("Waiting for event")
if event.wait(5):
print("event set.")
else:
print("Timed out.")
stop_event = threading.Event()
threading.Thread(target=flagger_thread, args=[stop_event]).start()
threading.Thread(target=waiter_thread, args=[stop_event]).start()
# wait for all threads to exit
for t in threading.enumerate():
if t != threading.current_thread():
t.join()
Waiting for event
event set.
问题是你的代码正在做一些与你的目标不同的事情。您的目标是“从子线程向主线程发送信号”,但您发布的示例代码正在监听子线程中的信号。
在您的示例代码中,有三个线程:
alarm(2)
(如果您只想做sleep(2)
,通常是一个坏主意)。sender
子线程。receiver
子线程。这是行不通的,因为信号只能从Python的主线程接收。这是一个非常严格的约束。它没有任何可用的星号或“除了……”情况——甚至连诱人的名字
signal.pthread_kill
也没有。
幸运的是,您的目标(处理主线程中的线程发送的信号)很容易实现,如下所示:
import signal
import threading
import os
import time
def signal_handler(num, stack):
print('Received signal %d in %s' % (num, threading.current_thread()))
signal.signal(signal.SIGUSR1, signal_handler)
def wait_for_signal():
print('Waiting for signal in', threading.current_thread())
signal.pause()
print('Done waiting')
def send_signal():
time.sleep(1)
print('Sending signal in', threading.current_thread())
os.kill(os.getpid(), signal.SIGUSR1)
sender = threading.Thread(target=send_signal, name='sender')
sender.start()
wait_for_signal()
sender.join() # Optional, but can't hurt