簡體   English   中英

如何與工作線程通信

[英]How to communicate with worker thread

我正在使用大量使用I / O的庫。 因此,對該庫的調用可能會持續很長時間(超過5秒)。 UI中直接使用它不是一個好主意,因為它將凍結。

因此,我將庫調用外包到線程隊列,如本例所示: Python線程:通信和停止

不過,我對此解決方案並不滿意,因為這有一個主要缺點:

  • 我真的無法與用戶界面進行交流。

每個lib命令都返回一條返回消息,該返回消息可以是錯誤消息或某些計算結果。 我怎么得到這個?

考慮一個庫調用do_test(foo)

def do_test(foo):
    time.sleep(10)
    return random.random() * foo

def ui_btn_click():
    threaded_queue.put((do_test, 42))
    # Now how to display the result without freezing the UI?

有人可以給我建議如何實現這種模式嗎?

編輯:這是一個最小的示例:

import os, time, random
import threading, queue

CMD_FOO = 1
CMD_BAR = 2

class ThreadedQueue(threading.Thread):
    def __init__(self):
        super().__init__()
        self.in_queue = queue.Queue()
        self.out_queue = queue.Queue()
        self.__stoprequest = threading.Event()

    def run(self):
        while not self.__stoprequest.isSet():
            (cmd, arg) = self.in_queue.get(True)

            if cmd == CMD_FOO:
                ret = self.handle_foo(arg)
            elif cmd == CMD_BAR:
                ret = self.handle_bar(arg)
            else:
                print("Unsupported cmd {0}".format(cmd))
            self.out_queue.put(ret)
            self.in_queue.task_done()

    def handle_foo(self, arg):
        print("start handle foo")
        time.sleep(10)
        return  random.random() * arg

    def handle_bar(self, arg):
        print("start handle bar")
        time.sleep(2)
        return (random.random() * arg, 2 * arg)


if __name__ == "__main__":
    print("START")
    t = ThreadedQueue()
    t.start()
    t.in_queue.put((CMD_FOO, 10))
    t.in_queue.put((CMD_BAR, 10))

    print("Waiting")

    while True:
        x = t.out_queue.get(True)
        t.out_queue.task_done()
        print(x)

我個人使用PySide但我不想將此庫依賴於PySide或任何其他與ui相關的庫。

我對自己的實現做了一些思考。 結論是,我啟動了另一個線程來選擇隊列結果:

class ReceiveThread(threading.Thread):
    """
    Processes the output queue and calls a callback for each message
    """
    def __init__(self, queue, callback):
        super().__init__()
        self.__queue = queue
        self.__callback = callback
        self.__stoprequest = threading.Event()
        self.start()

    def run(self):
        while not self.__stoprequest.isSet():
            ret = self.__queue.get(True)
            self.__callback(ret)
            self.__queue.task_done()

來自UI或其他位置的給定回調將與隊列中的每個結果一起調用。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM