【问题标题】:Can semaphores in python 2.7 work with just targetting a metod to a thread?python 2.7中的信号量可以仅将方法定位到线程吗?
【发布时间】:2017-03-22 21:43:59
【问题描述】:

我要做的是运行或暂停两个不同的功能,具体取决于它们各自的选项按钮是否处于活动状态(这两个功能的执行是互斥的)我尝试根据 Jay @987654321 给出的答案使用信号量@ 但两个线程似乎都在继续运行。这是我正在编写的代码(它在 __init__ 块内):

self.manual_sema = Semaphore(0)
self.auto_sema = Semaphore(0)

#Function A.

def Exec_Manual():
    while True:
        for i in range(0,5):
            if self.rbtnMan.isChecked():
                if self.rbtnAuto.isChecked():
                    self.manual_sema.acquire()
                    self.auto_sema.release()
                    break
                self._tx_freq1_line_edit.setEnabled(1)
                self._tx_freq2_line_edit.setEnabled(1)
                self._tx_freq3_line_edit.setEnabled(1)
                self._tx_freq4_line_edit.setEnabled(1)
                self._tx_freq5_line_edit.setEnabled(1)
                frec = 'self._tx_freq'+str(i+1)+'_line_edit.text()'
                efrec = float(eval(frec))
                self.lblTx1.setText(str(efrec-0.4))
                self.lblTx2.setText(str(efrec))
                self.lblTx3.setText(str(efrec+0.4))
                #print frec
                print efrec
                print threading.currentThread().getName()
                for th in threading.enumerate():
                    print th
                time.sleep(1)

manual_thread = threading.Thread(target=Exec_Manual, name='manual_thread')
manual_thread.daemon = True
manual_thread.start()

#Function B.

def Exec_Auto():  
    while True:
        for i in range(0,17):
            if self.rbtnAuto.isChecked():
                if self.rbtnMan.isChecked():
                    self.auto_sema.acquire()
                    self.manual_sema.release()
                    break
                self._tx_freq1_line_edit.setDisabled(1)
                self._tx_freq2_line_edit.setDisabled(1)
                self._tx_freq3_line_edit.setDisabled(1)
                self._tx_freq4_line_edit.setDisabled(1)
                self._tx_freq5_line_edit.setDisabled(1)
                frec0=88.5
                x=i*1.2
                efrec = float(frec0)+x
                print efrec
                print threading.currentThread().getName()#Debug
                for th in threading.enumerate():
                    print th
                self.lblTx1.setText(str(efrec-0.4))
                self.lblTx2.setText(str(efrec))
                self.lblTx3.setText(str(efrec+0.4))
                time.sleep(1)
                frec0=frec0+1.2

auto_thread = threading.Thread(target=Exec_Auto, name='auto_thread')
auto_thread.daemon = True
auto_thread.start()

auto_thread 和 manual_thread 似乎都在继续执行,因为threading.enumerate() 一直显示它们处于活动状态(我希望它们在选中另一个函数的单选按钮时消失,并在再次选中它们自己的单选按钮时重新启动):

<_MainThread(MainThread, started 140030203459328)>
<Thread(manual_thread, started daemon 140029502768896)>
<Thread(auto_thread, started daemon 140029154293504)>

在 Jay here 给出的答案中,我可以看到他正在创建继承自 thread 的类并将函数放入这些类中。 ¿ 这可能是获得我所期望的行为需要做的事情吗? ¿您能否提供一些关于如何让我的代码按预期工作的想法?一如既往,提前感谢。

问候, 罗恩

【问题讨论】:

  • 抱歉,问题很糟糕,我在写完整个描述后阅读了它,发现它可能不代表我实际要问的问题。希望我能解释一下自己。
  • threading.enumerate 将显示他们都活着,因为即使他们碰巧在信号量上等待,他们也活着。
  • 我假设rbtnAutorbtnMan 是同一个单选按钮组的一部分并且不能同时设置?如果 rbtnAuto 没有被选中,那么说状态是手动的是否公平?
  • 感谢@tdelaney 的回答是的,当一个单选按钮被选中时,另一个不能。
  • 至于资源使用...例如看Exec_Manual。如果if self.rbtnMan.isChecked(): 为真,你做一些工作然后睡1 秒。但如果它是假的,你会立即重新运行循环并再次检查。你正在把系统搞得一团糟。

标签: python multithreading python-2.7 python-multithreading


【解决方案1】:

我认为尝试同步线程比它的价值更麻烦。您需要考虑时间窗口,例如两个线程碰巧检查​​它们时的 GUI 更改状态。从函数中取出逻辑并在每个循环上调用一个或另一个更高级别的函数会更容易。该函数可以告诉工作函数是否存在需要更改 gui 的状态更改。

def Exec_Manual(state_changed):
    if state_changed:
        self._tx_freq1_line_edit.setEnabled(1)
        self._tx_freq2_line_edit.setEnabled(1)
        self._tx_freq3_line_edit.setEnabled(1)
        self._tx_freq4_line_edit.setEnabled(1)
        self._tx_freq5_line_edit.setEnabled(1)
    frec = 'self._tx_freq'+str(i+1)+'_line_edit.text()'
    efrec = float(eval(frec))
    self.lblTx1.setText(str(efrec-0.4))
    self.lblTx2.setText(str(efrec))
    self.lblTx3.setText(str(efrec+0.4))
    time.sleep(1)

def Exec_Auto(state_changed):  
    if state_changed:
        self._tx_freq1_line_edit.setDisabled(1)
        self._tx_freq2_line_edit.setDisabled(1)
        self._tx_freq3_line_edit.setDisabled(1)
        self._tx_freq4_line_edit.setDisabled(1)
        self._tx_freq5_line_edit.setDisabled(1)
    frec0=88.5
    x=i*1.2
    efrec = float(frec0)+x
    self.lblTx1.setText(str(efrec-0.4))
    self.lblTx2.setText(str(efrec))
    self.lblTx3.setText(str(efrec+0.4))
    time.sleep(1)

def the_decider():
    state = self.rbtnAuto.isChecked()
    while True:
        new_state = self.rbtnAuto.isChecked()
        if new_state:
            Exec_Auto(state == new_state)
        else:
            Exec_Manual(state == new_state)
        state = new_state

auto_thread = threading.Thread(target=the_decider, name='the_decider')
auto_thread.start()

【讨论】:

  • 谢谢@tdelaney,我要试试这个。如果它可能有帮助,另一个问题是,当程序启动时,它在资源监视器中显示 CPU 使用率至少低于 50%,但是当我单击另一个单选按钮时,CPU 使用率达到 100%(代码仍在运行并且 GUI 不会冻结)
  • 我尝试了您的代码,它有点像我预期的那样工作(CPU 使用率大约不到 50%),但它不会更改标签中的值(例如,在 Exec_Auto 函数中,它应该是以 3) 为一组呈现 FM 幽灵的每个频率,这是我通过使用您删除的 for 循环获得的。您删除 for 循环有什么原因吗?
  • 我并没有太在意那个内在,因为它似乎与手头的问题无关...... TL;我想!无论如何,你可以坚持下去。
  • 我刚刚添加了 for 循环,它非常有效!伙计,只有大约 30% 的 CPU 使用率。我希望我能给你买杯啤酒。谢谢你,真的。
  • 大声笑......我明天晚上会在棉花谷。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-05-13
  • 2023-04-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多