2015-06-09 74 views
0

我在使用python線程時遇到了一些麻煩。我正在編寫一個軟件包,用於繪製從多個設備接收的數據。我有一個繪圖線程,它會在數據收到來自所有設備的一組數據以及每個設備的數據檢索線程後繪製數據。應用程序不斷繪製數據(與從設備中檢索數據一樣快),直到用戶點擊按鈕。我有一個threading.Event()self.stop_thread被頻繁檢查以退出線程循環。根據我的調試器和threading.active_count(),線程碰到檢查點,跳出循環,但仍然「運行」。有誰知道爲什麼會發生這種情況,我該如何讓它停止?我需要知道在移動到應用程序的另一個功能之前,這些線程已經消失。以下三種方法是問題出現的地方。python線程在目標方法執行完畢後沒有終止

# initalizes startup settings, starts a thread to carry out 
# plotting and a seperate thread to carry out data retrieval 
def start_plot_threads(self): 
    if not self.abstraction.connected: 
     self.connect_to_device() 
     if not self.abstraction.connected: 
      return 
    self.stop_thread.clear() 
    self.pause_thread.clear() 
    for device in self.devices: 
     device.pause_thread.clear() 
     device.stop_thread.clear() 
     device.change_units.set() 
    self.presentation.enable_derivative() 
    self.presentation.show_average_button.SetValue(False) 
    self.presentation.show_average_button.Disable() 
    self.abstraction.multi_plot_data = {} 
    try: 
     if self.plot_thread.is_alive(): 
      return 
    except Exception: 
     pass 
    self.plot_thread = Thread(target=self.plot_data) 
    self.plot_thread.daemon = True 
    self.plot_thread.start() 
    for device in self.devices: 
     thread = Thread(target=self.retrieve_data, 
         kwargs={'device': device}, 
         name="Data Retrieval Thread %s" % device.instr_id) 
     thread.daemon = True 
     thread.start() 

# waits for plot data to be thrown on a thread safe queue by the data 
# retrieval thread and plots it. data comes in as a tuple of the form 
# (y_data, label, x_data) 
def plot_data(self): 
    multiplot = False 
    if len(self.devices) > 1: 
     multiplot = True 
     plot_data = [] 
    while not self.stop_thread.is_set(): 
     try: 
      data = self.plot_data_queue.get() 
     except Empty: 
      pass 
     else: 
      if multiplot: 
       scan = {} 
       scan['y_data'] = [data[0]] 
       scan['labels'] = [data[1]] 
       scan['x_data'] = data[2] 
       plot_data.append(scan) 
       if len(plot_data) == len(self.devices): 
        self.presentation.plot_multiline(plot_data, average=False) 
        self.abstraction.multi_plot_data = plot_data 
        plot_data = [] 
      else: 
       self.presentation.plot_signal(data[0], data[1]) 

# the intent is that the data retrieval thread stays in this loop while 
# taking continuous readings 
def retrieve_data(self, device): 
    while True: 
     if device.stop_thread.is_set(): 
      return 
     while device.pause_thread.is_set(): 
      if device.stop_thread.is_set(): 
       return 
      sleep(0.1) 
     y = self.get_active_signal_data(device) 
     if not y: 
      return 
     self.plot_data_queue.put(
      (y, device.name, device.x_data)) 
     self.abstraction.y_data = [y] 
     try: 
      self.update_spectrum(device) 
     except DeviceCommunicationError, data: 
      self.presentation.give_connection_error(data) 
     self.presentation.integ_time = device.prev_integ 

對於方法中額外的體積,我表示歉意。他們是直接從我的代碼庫。

+0

爲什麼你設置'守護= TRUE;你的主題? –

+0

我設置了daemon = True,以便在主線程終止時應用程序將退出。我並不擔心數據丟失或者線程是否完成了他們的任務。我只需要確保線程在移動到應用程序的另一個函數之前就被終止了。 – jgramse

回答

0

爲什麼你的線程繼續運行的原因是unknown- device.stop_thread.is_set():(什麼是做設置?)

但是你能保證你的所有線程都停止通過保留每個線程的處理程序(通過附加每個線程對象列表),並且一旦你開始了你的所有線程,你就可以繼續到它們的thread.join()

threads = [] 
for job in batch: 
    thr = threading.Thread(target=do_job, args = (job)) 
    thr.start() 
    threads.append(thr) 
#join all the threads 
for thr in threads: 
    thr.join() 

加入將等待線程完成後再繼續。

Python文檔: https://docs.python.org/2/library/threading.html

+0

stop_thread.set()在用戶單擊應用程序中的許多按鈕之一時調用。它被正確設置,正確檢查,目標方法的執行正確返回。我曾嘗試thread.join()(我有線程保存在列表中的一個點),但它只是永遠停留在該阻止調用join()。線程沒有執行任何任務,因爲他們已經離開了他們的目標方法。他們只是跑......永遠......我不知道爲什麼。 – jgramse

+0

thread.join()會做你期望的,所以你應該回到那個代碼。我打賭你的問題在於http://stackoverflow.com/questions/1294382/what-is-a-global-interpreter-lock-gil基本上你需要知道的是,如果你沒有和你的代碼中的執行中斷,其他線程將完全(或幾乎)阻塞運行。如果你在其他地方的閱讀循環中實現一些time.sleep,這將使其他線程有機會運行。 – John

+0

謝謝約翰。不知道爲什麼它不工作之前,但thread.join()似乎現在正在工作。 – jgramse

相關問題