2012-03-21 34 views
23

Tôi đang cố viết một phương thức đếm ngược đến một thời điểm nhất định và trừ khi có lệnh khởi động lại, nó sẽ thực thi tác vụ. Nhưng tôi không nghĩ rằng lớp Python threading.Timer cho phép hẹn giờ có thể hủy được.Luồng có thể hủy.Tìm hiểu bằng Python

import threading 

def countdown(action): 
    def printText(): 
     print 'hello!' 

    t = threading.Timer(5.0, printText) 
    if (action == 'reset'): 
     t.cancel() 

    t.start() 

Tôi biết mã ở trên là sai bằng cách nào đó. Sẽ đánh giá cao một số hướng dẫn loại ở đây.

Trả lời

12

Tôi không chắc liệu tôi có hiểu chính xác hay không. Bạn có muốn viết một cái gì đó giống như trong ví dụ này?

>>> import threading 
>>> t = None 
>>> 
>>> def sayHello(): 
...  global t 
...  print "Hello!" 
...  t = threading.Timer(0.5, sayHello) 
...  t.start() 
... 
>>> sayHello() 
Hello! 
Hello! 
Hello! 
Hello! 
Hello! 
>>> t.cancel() 
>>> 
+0

Đó là _almost_ tốt. Nó sẽ được * tốt * nếu chương trình của bạn đã không chấm dứt ngay lập tức, với một "Hello" và không có sự chậm trễ nào cả! :) Bạn phải kết hợp 't.cancel()' vào hàm 'sayHello()' dựa trên một số điều kiện, ví dụ: 'if counter == 10: t.cancel()'. Sau đó nó sẽ có một ý nghĩa. – Apostolos

+0

Xin lỗi. Nó sẽ không được tốt ngay cả sau đó. Nếu bạn thêm bất kỳ mã nào sau khi gọi 'sayHello (0)', nó sẽ được thực hiện trước khi kiểm tra bộ đếm thời gian kết thúc! (Hãy tự mình thử nghiệm, bằng cách thêm ví dụ: "in" Xong "' ở cuối mã của bạn.) – Apostolos

25

Bạn sẽ gọi phương thức hủy bỏ sau khi bạn bắt đầu hẹn giờ:

import time 
import threading 

def hello(): 
    print "hello, world" 
    time.sleep(2) 

t = threading.Timer(3.0, hello) 
t.start() 
var = 'something' 
if var == 'something': 
    t.cancel() 

Bạn có thể xem xét sử dụng một thời gian vòng lặp trên một Thread, thay vì sử dụng một hẹn giờ.
Dưới đây là một ví dụ trích lập từ Nikolaus Gradwohl của answer đến một câu hỏi khác:

import threading 
import time 

class TimerClass(threading.Thread): 
    def __init__(self): 
     threading.Thread.__init__(self) 
     self.event = threading.Event() 
     self.count = 10 

    def run(self): 
     while self.count > 0 and not self.event.is_set(): 
      print self.count 
      self.count -= 1 
      self.event.wait(1) 

    def stop(self): 
     self.event.set() 

tmr = TimerClass() 
tmr.start() 

time.sleep(3) 

tmr.stop() 
+0

Vui lòng giải thích lý do bạn cho rằng vòng lặp thời gian là ý tưởng tốt hơn so với bộ hẹn giờ có chuỗi. –

+1

@WesModes Tôi cung cấp một giải pháp thay thế để in đếm ngược. –

+0

Làm việc cho tôi. Mặc dù tôi được sử dụng trong khi không self.event.wait (1) để thực hiện một cái gì đó mỗi giây thay vì một biến đếm – mtosch

6

Các threading.Timer lớp không có một phương pháp cancel, và mặc dù nó sẽ không hủy bỏ chủ đề, nó sẽ ngừng đồng hồ đếm từ thực sự bắn. Điều thực sự xảy ra là phương thức cancel đặt một threading.Event và luồng thực sự thực thi threading.Timer sẽ kiểm tra sự kiện đó sau khi thực hiện xong và trước khi thực sự thực thi cuộc gọi lại.

Điều đó nói rằng, bộ hẹn giờ thường được thực hiện mà không cần bằng cách sử dụng một chuỗi riêng biệt cho từng cái. Cách tốt nhất để làm điều đó phụ thuộc vào những gì chương trình của bạn đang thực sự làm (trong khi chờ đợi bộ đếm thời gian này), nhưng bất cứ điều gì với một vòng lặp sự kiện, như GUI và khung mạng, tất cả đều có cách để yêu cầu một bộ đếm thời gian được nối vào eventloop.

0

Lấy cảm hứng từ bài đăng ở trên. Có thể hủy và đặt lại bộ hẹn giờ bằng Python. Nó sử dụng thread.
Các tính năng: Khởi động, Dừng, Khởi động lại, chức năng gọi lại.
Nhập: Thời gian chờ, giá trị sleep_chunk và callback_function.
Có thể sử dụng hoặc kế thừa lớp này trong bất kỳ chương trình nào khác. Cũng có thể chuyển đối số cho hàm gọi lại.
Bộ hẹn giờ cũng sẽ phản hồi ở giữa. Không chỉ sau khi hoàn thành thời gian ngủ đầy đủ. Vì vậy, thay vì sử dụng một giấc ngủ đầy đủ, sử dụng các đoạn nhỏ của giấc ngủ và tiếp tục kiểm tra đối tượng sự kiện trong vòng lặp.

import threading 
import time 

class TimerThread(threading.Thread): 
    def __init__(self, timeout=3, sleep_chunk=0.25, callback=None, *args): 
     threading.Thread.__init__(self) 

     self.timeout = timeout 
     self.sleep_chunk = sleep_chunk 
     if callback == None: 
      self.callback = None 
     else: 
      self.callback = callback 
     self.callback_args = args 

     self.terminate_event = threading.Event() 
     self.start_event = threading.Event() 
     self.reset_event = threading.Event() 
     self.count = self.timeout/self.sleep_chunk 

    def run(self): 
     while not self.terminate_event.is_set(): 
      while self.count > 0 and self.start_event.is_set(): 
       # print self.count 
       # time.sleep(self.sleep_chunk) 
       # if self.reset_event.is_set(): 
       if self.reset_event.wait(self.sleep_chunk): # wait for a small chunk of timeout 
        self.reset_event.clear() 
        self.count = self.timeout/self.sleep_chunk # reset 
       self.count -= 1 
      if self.count <= 0: 
       self.start_event.clear() 
       #print 'timeout. calling function...' 
       self.callback(*self.callback_args) 
       self.count = self.timeout/self.sleep_chunk #reset 

    def start_timer(self): 
     self.start_event.set() 

    def stop_timer(self): 
     self.start_event.clear() 
     self.count = self.timeout/self.sleep_chunk # reset 

    def restart_timer(self): 
     # reset only if timer is running. otherwise start timer afresh 
     if self.start_event.is_set(): 
      self.reset_event.set() 
     else: 
      self.start_event.set() 

    def terminate(self): 
     self.terminate_event.set() 

#================================================================= 
def my_callback_function(): 
    print 'timeout, do this...' 

timeout = 6 # sec 
sleep_chunk = .25 # sec 

tmr = TimerThread(timeout, sleep_chunk, my_callback_function) 
tmr.start() 

quit = '0' 
while True: 
    quit = raw_input("Proceed or quit: ") 
    if quit == 'q': 
     tmr.terminate() 
     tmr.join() 
     break 
    tmr.start_timer() 
    if raw_input("Stop ? : ") == 's': 
     tmr.stop_timer() 
    if raw_input("Restart ? : ") == 'r': 
     tmr.restart_timer() 
Các vấn đề liên quan