- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
线程未按我预期的方式工作。
我有一个可行的解决方案,我可以使用 Raspberry Pi 和簧片开关监控冰箱何时打开和关闭(声音的播放未暂停和暂停)。我现在想添加一个计时器,以便在门打开时间过长时执行某些操作。我想启动一个线程,它会在警报操作之前休眠 x 秒是个好主意。当开关再次关闭时,我会用信号杀死线程。
我的方法失败了。 CountDown 运行线程已启动,但终止信号命令已执行但没有效果。此外,不会执行 c.terminate()
之后的命令。我查看了线程示例,但它们似乎适用于更复杂的情况。我错过了什么?
代码:
#!/usr/bin/env python2.7
import threading, subprocess, sys, time, syslog
import RPi.GPIO as GPIO
sound = "/home/pi/sounds/fridge_link.mp3" # sound to play while switch is open
cmd = ['mplayer', '-nolirc', '-noconsolecontrols', '-slave', '-quiet', sound] # command to play sound
lim = 10 # seconds until warning
# thread for countdown (should be interruptable)
# based on http://chimera.labs.oreilly.com/books/1230000000393/ch12.html#_solution_197
class CountdownTask:
def __init__(self):
self._running = True
def terminate(self):
self._running = False
print("thread killed")
def run(self, n):
print("start timer")
time.sleep(n)
## action when timer isup
print("timer ended")
c = CountdownTask()
t = threading.Thread(target=c.run, args=(lim,))
t.daemon = True
p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stdin=subprocess.PIPE)
p.stdin.write('\npausing_keep pause\n')
REED = 27 # data pin of reed sensor (in)
# GPIO setup
GPIO.setwarnings(False)
GPIO.setmode(GPIO.BCM)
GPIO.setup(REED,GPIO.IN, pull_up_down=GPIO.PUD_DOWN)
def edge(channel):
if GPIO.input(REED):
print("detect close")
c.terminate()
p.stdin.write('\npause\n')
pass
else:
print("detect open")
t.start()
p.stdin.write('\npausing_toggle pause\n')
def main():
GPIO.add_event_detect(REED, GPIO.BOTH,callback=edge,bouncetime=1000)
while True:
time.sleep(0.2)
pass
#------------------------------------------------------------
if __name__ == "__main__": main()
新版本:
#!/usr/bin/env python2.7
import threading, subprocess, sys, time, syslog
import RPi.GPIO as GPIO
sound = "/home/pi/sounds/fridge_link.mp3" # sound to play while switch is open
cmd = ['mplayer', '-nolirc', '-noconsolecontrols', '-slave', '-quiet', sound] # command to play sound
lim = 10 # seconds until warning
# thread for countdown (should be interruptable)
class CountdownTask:
global dooropen
def __init__(self):
self._running = True
def terminate(self):
self._running = False
print("thread killed")
def run(self, n):
while self._running and dooropen == False:
time.sleep(0.2)
pass
while self._running and dooropen:
print("start timer")
time.sleep(n)
## action when timer isup
print("timer ended")
c = CountdownTask()
t = threading.Thread(target=c.run, args=(lim,))
t.daemon = True
p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stdin=subprocess.PIPE)
p.stdin.write('\npausing_keep pause\n')
REED = 27 # data pin of reed sensor (in)
# GPIO setup
GPIO.setwarnings(False)
GPIO.setmode(GPIO.BCM)
GPIO.setup(REED,GPIO.IN, pull_up_down=GPIO.PUD_DOWN)
dooropen = False # assuming door's closed when starting
def edge(channel):
global dooropen
if GPIO.input(REED): # * no longer reached
if dooropen == False: # catch fridge compressor spike
print("false close alert")
return
p.stdin.write('\npause\n')
dooropen = False
pass
else:
print("detect open")
if dooropen == True:
print("false open alert")
return
p.stdin.write('\npausing_toggle pause\n')
dooropen = True
def main():
GPIO.add_event_detect(REED, GPIO.BOTH,callback=edge,bouncetime=1000)
t.start()
while True:
time.sleep(0.2)
pass
#------------------------------------------------------------
if __name__ == "__main__": main()
调整后的部分,现在工作:
def run(self, n):
while self._running and dooropen == False:
time.sleep(0.2)
pass
while self._running and dooropen:
time.sleep(n)
if dooropen:
## action when timer isup
最佳答案
您通过 self._running
编写的线程终止机制不起作用,因为您没有在 run( )
胎面的方法(实际上是在您所指的示例中完成的)。
定期轮询增加了这里不需要的复杂性。您应该以一种简单可靠的不同方式构建您的逻辑。示例代码:
import threading
import time
dooropen = True
def warnafter(timeout):
time.sleep(timeout)
if dooropen:
print("Warning!")
t = threading.Thread(target=warnafter, args=(2,))
t.start()
time.sleep(1)
dooropen = False
t.join()
将 time.sleep(1)
更改为 time.sleep(3)
并打印警告。为什么这样做有效?这如何转化为您的用例?
首先,让我们给事物命名。你有你的主线程和“警告线程”。这些是我的示例代码中架构的基石:
在两个线程之间共享一个状态,指示门是否打开,转化为是否应发出警告的事实。我们称此状态为 dooropen
,它可以是 True
或 False
。它是一个可在主线程范围和警告线程可访问范围内访问的变量。也就是说,它存在于共享内存中。
这是您的约定:dooropen
仅从主线程编写。警告线程只读取它。
只要您认为合适的时间,就生成您的警告线程。使其休眠(确切的休眠时间可能不可靠,尤其是在嵌入式系统上)。
关键部分:在 warn 线程发出警报之前,让它检查 dooropen
状态。如果没有开门
,就不要发出警报!
您看到这两种不同的范例了吗?
您的范例是放置一个武装炸弹,该炸弹被编程为在给定的时间后爆炸。这个炸弹不会再和你顶嘴了。你希望你能够在炸弹爆炸前拆除/摧毁炸弹,如果你不再需要它爆炸的话。
我提议的范例运送的炸弹实际上在需要时才配备。在你的炸弹即将爆炸的时间点,这枚炸弹询问是否真的应该这样做,然后才自行武装并爆炸。
鉴于后一种范例,如果警告线程被告知不要执行其操作,它会静默自行退出。不需要“从外部终止线程”的概念!
在实践中,您需要更高级的概念,其中警告线程有它自己的 active
开关。也就是说,您的主线程可以以受控方式停用单个警告线程。看这个例子:
import threading
import time
class WarnThread(threading.Thread):
def __init__(self, timeout, name):
threading.Thread.__init__(self)
self._timeout = timeout
self.active = True
self.name = name
self.start()
def run(self):
self._warnafter()
def _warnafter(self):
time.sleep(self._timeout)
if self.active:
print("WarnThread %s: Warning after timeout" % self.name)
ws = [WarnThread(2, i) for i in range(5)]
# Simulate spending some time doing other things,
# such as responding to external events.
time.sleep(1)
# Selectively deactivate some of the warn threads.
ws[0].active = False
ws[2].active = False
for w in ws:
w.join()
输出:
WarnThread 4: Warning after timeout
WarnThread 1: Warning after timeout
WarnThread 3: Warning after timeout
关于python - 如何正确使用倒计时线程,如何过早停止它?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28459996/
我在网上搜索但没有找到任何合适的文章解释如何使用 javascript 使用 WCF 服务,尤其是 WebScriptEndpoint。 任何人都可以对此给出任何指导吗? 谢谢 最佳答案 这是一篇关于
我正在编写一个将运行 Linux 命令的 C 程序,例如: cat/etc/passwd | grep 列表 |剪切-c 1-5 我没有任何结果 *这里 parent 等待第一个 child (chi
所以我正在尝试处理文件上传,然后将该文件作为二进制文件存储到数据库中。在我存储它之后,我尝试在给定的 URL 上提供文件。我似乎找不到适合这里的方法。我需要使用数据库,因为我使用 Google 应用引
我正在尝试制作一个宏,将下面的公式添加到单元格中,然后将其拖到整个列中并在 H 列中复制相同的公式 我想在 F 和 H 列中输入公式的数据 Range("F1").formula = "=IF(ISE
问题类似于this one ,但我想使用 OperatorPrecedenceParser 解析带有函数应用程序的表达式在 FParsec . 这是我的 AST: type Expression =
我想通过使用 sequelize 和 node.js 将这个查询更改为代码取决于在哪里 select COUNT(gender) as genderCount from customers where
我正在使用GNU bash,版本5.0.3(1)-发行版(x86_64-pc-linux-gnu),我想知道为什么简单的赋值语句会出现语法错误: #/bin/bash var1=/tmp
这里,为什么我的代码在 IE 中不起作用。我的代码适用于所有浏览器。没有问题。但是当我在 IE 上运行我的项目时,它发现错误。 而且我的 jquery 类和 insertadjacentHTMl 也不
我正在尝试更改标签的innerHTML。我无权访问该表单,因此无法编辑 HTML。标签具有的唯一标识符是“for”属性。 这是输入和标签的结构:
我有一个页面,我可以在其中返回用户帖子,可以使用一些 jquery 代码对这些帖子进行即时评论,在发布新评论后,我在帖子下插入新评论以及删除 按钮。问题是 Delete 按钮在新插入的元素上不起作用,
我有一个大约有 20 列的“管道分隔”文件。我只想使用 sha1sum 散列第一列,它是一个数字,如帐号,并按原样返回其余列。 使用 awk 或 sed 执行此操作的最佳方法是什么? Accounti
我需要将以下内容插入到我的表中...我的用户表有五列 id、用户名、密码、名称、条目。 (我还没有提交任何东西到条目中,我稍后会使用 php 来做)但由于某种原因我不断收到这个错误:#1054 - U
所以我试图有一个输入字段,我可以在其中输入任何字符,但然后将输入的值小写,删除任何非字母数字字符,留下“。”而不是空格。 例如,如果我输入: 地球的 70% 是水,-!*#$^^ & 30% 土地 输
我正在尝试做一些我认为非常简单的事情,但出于某种原因我没有得到想要的结果?我是 javascript 的新手,但对 java 有经验,所以我相信我没有使用某种正确的规则。 这是一个获取输入值、检查选择
我想使用 angularjs 从 mysql 数据库加载数据。 这就是应用程序的工作原理;用户登录,他们的用户名存储在 cookie 中。该用户名显示在主页上 我想获取这个值并通过 angularjs
我正在使用 autoLayout,我想在 UITableViewCell 上放置一个 UIlabel,它应该始终位于单元格的右侧和右侧的中心。 这就是我想要实现的目标 所以在这里你可以看到我正在谈论的
我需要与 MySql 等效的 elasticsearch 查询。我的 sql 查询: SELECT DISTINCT t.product_id AS id FROM tbl_sup_price t
我正在实现代码以使用 JSON。 func setup() { if let flickrURL = NSURL(string: "https://api.flickr.com/
我尝试使用for循环声明变量,然后测试cols和rols是否相同。如果是,它将运行递归函数。但是,我在 javascript 中执行 do 时遇到问题。有人可以帮忙吗? 现在,在比较 col.1 和
我举了一个我正在处理的问题的简短示例。 HTML代码: 1 2 3 CSS 代码: .BB a:hover{ color: #000; } .BB > li:after {
我是一名优秀的程序员,十分优秀!