亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

Tkinter GUI、I/O 和線程:何時使用隊列,何時使用事件?

Tkinter GUI、I/O 和線程:何時使用隊列,何時使用事件?

繁花如伊 2023-05-23 14:55:26
我正在使用 TKinter 構建一個 GUI(用于與多通道分析儀的套接字連接)以定期(~15 秒)接收和繪制數據(~15.000.000 值)。在接收數據時,我不希望 GUI 凍結,所以我使用多線程進行連接處理、數據接收和繪圖操作。正如在可重現的代碼中看到的那樣,我通過設置一個事件并threading.Event()一個接一個地處理線程(initSettings()&中的幾行代碼acquireAndPlotData)來實現這一點。我唯一一次干擾 GUI 是在繪制到畫布時 & 我使用 tkintersafter()方法執行此操作。啟動時,只要窗口打開并按預期工作,代碼就會運行而不會凍結并接收和繪圖。當我讀到在 tkinter GUI 中處理阻塞 I/O 操作時,我只找到了遞歸排隊和檢查隊列的示例(使用Queue&?after(),?1?2?3?4?5?),但我發現它更方便,更容易處理這些操作threading.Event()?,F在我的問題是:我是在使用正確的方法還是在這里遺漏了一些重要的東西?(關于線程安全,競爭條件,如果繪圖失敗并且花費的時間比數據采集時間長怎么辦?我沒有想到的東西?不良做法?等等......)我將非常感謝您對此事的反饋!
查看完整描述

1 回答

?
波斯汪

TA貢獻1811條經驗 獲得超4個贊

所以我這樣做了,但我不知道它是否適合你,或者這是否是一個很好的方法,但它可以像評論中所述那樣保護你,它的好處是.after你的函數do_stuff只在需要時被調用.


import tkinter as tk

import time

import threading


def get_data():

? ? time.sleep(3)

? ? print('sleeped 3')

? ? _check.set(1)


def do_stuff():

? ? try:

? ? ? ? root.configure(bg='#'+str(_var.get()))

? ? ? ? _var.set(_var.get()+101010)

? ? except:

? ? ? ? _var.set(101010)


root = tk.Tk()

_check = tk.IntVar(value=0)

_var = tk.IntVar(value=101010)



def callback(event=None, *args):

? ? t1 = threading.Thread(target=get_data)

? ? t1.start()

? ??

? ? do_stuff()

? ??

_check.trace_add('write', callback) #kepp track of that variable and trigger callback if changed

callback() # start the loop




root.mainloop()

一些研究:

interpreter 僅在創建它的線程中有效,所有 Tk 活動也必須在該線程中發生。這意味著必須在創建解釋器的線程中調用主循環。可以從其他線程調用命令;_tkinter 將為解釋器線程排隊一個事件,然后解釋器線程將執行命令并傳回結果。

#l1493?var_invoke

?The?current?thread?is?not?the?interpreter?thread.??Marshal

???????the?call?to?the?interpreter?thread,?then?wait?for

???????completion.?*/????if?(!WaitForMainloop(self))??
?????????????return?NULL;

在 python 線程中使用 intvar-doublevar 是否安全

當您設置一個變量時,它會在與該變量關聯的主控件上調用 globalsetvar 方法。_tk.globalsetvar 方法在 C 中實現,并在內部調用 var_invoke,后者在內部調用 WaitForMainLoop,它將嘗試安排命令在主線程中執行,如我上面引用的 _tkinter 源中所述。

? ? ?Start

? ? ? ?|

? ? ? ?|<----------------------------------------------------------+

? ? ? ?v? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?^

? ?Do I have? ? No[*]? Calculate how? ? ? ? ? ? Sleep for at? ? ? ?|

? ?work to do?? -----> long I may sleep? -----> most that much --->|

? ? ? ?|? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? time? ? ? ? ? ? ? ?|

? ? ? ?| Yes? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?|

? ? ? ?|? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?|

? ? ? ?v? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?|

? ?Do one callback? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?|

? ? ? ?|? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?|

? ? ? ?+-----------------------------------------------------------+

常識

來自錯誤追蹤器:

Tkinter 和線程。

如果你想同時使用 tkinter 和線程,最安全的方法是在主線程中進行所有 tkinter 調用。如果工作線程生成 tkinter 調用所需的數據,請使用 queue.Queue 將數據發送到主線程。為了徹底關閉,添加一個方法來等待線程停止并在按下窗口關閉按鈕 [X] 時調用它。

效果機器人

只需在主線程中運行所有 UI 代碼,讓編寫器寫入一個 Queue 對象;例如

結論

你做事的方式和我做事的方式似乎很理想,但它們似乎一點也沒錯。這取決于需要什么。


查看完整回答
反對 回復 2023-05-23
  • 1 回答
  • 0 關注
  • 197 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號