2016-02-22 51 views
1

我想從背景回調中執行我的代碼到主線程中。由於某些原因,我沒有找到簡單的例子來執行此操作。如何從另一個線程上調用的回調函數返回到主線程

我發現隊列和池的例子,這顯然不是我想要的。我只想加入主線程來執行我的功能。

下面是一些簡單的代碼:

def my_callback: 
    # this callback is called from a third party and I don't have control on it. 
    # But because of this, the function must_be_executed_on_main_thread is 
    # executed on the background. 
    must_be_executed_on_main_thread() 

def must_be_executed_on_main_thread: 
    # must be executed on the main thread. 

**編輯**

這裏是我的問題: 主文件:

if __main__ == '__main__' 
    sio = socketio.Server() 
    app = Flask(__name__) 
    app = socketio.Middleware(sio, app) 

    # now the thread is blocking into the server pool 
    eventlet.wsgi.server(eventlet.listen('', 7000)), app) 

從另一個文件,我有一位處理插座事件的裝飾者:

@sio.on('test') 
def test(sid, data): 
    print threading.currentThread() 
    sio.emit('event triggered') 

這裏是問題:我有一些硬件按鈕觸發的事件,這會觸發一個稱爲sio「測試」事件的回調。但由於事件不會被觸發到同一個線程,這使我有些麻煩:

# async call ! 
def event_cb(num): 
    sio.emit('test') 

GPIO.add_event_detect(btNumber, GPIO.RISING, event_cb) 

的測試方法裝飾叫做: 但是當EMIT不是主線程上完成,這個停止工作。

只要套接字調用是從Mainthread就可以了。 但是當一個電話完成DummyThread,這不工作了。

我使用socket.io實現在客戶端設備上進行測試。只要「排出」在主線上完成,它就可以工作,但是當我在另一個線程上執行時(例如觸發回叫的按鈕,它將停止工作)

這就是爲什麼我喜歡執行

+0

「停止工作」不是問題的明確描述。 如果你不想'wsgi.server'來阻塞主線程,請執行'eventlet.spawn(eventlet.wsgi.server,listen(...),app)'。不要忘記定期調用'eventlet.sleep(0)'以確保Eventlet主循環有機會處理網絡事件。 此外,您可以嘗試'monkey_patch(threading = True)',這樣總會有一個操作系統線程。 也要注意「按鈕反彈」(谷歌它)。使用按鈕的正確方法是使用Linux gpio-keys或通過採樣手動去除。 – temoto

+0

根據性能要求,自己做循環(而不是由某個庫中的C)可能可行也可能不可行。它絕對會工作。 :) –

回答

2

通過使用Queue實例,您可以輕鬆地在線程之間傳遞值。

這個簡單的演示腳本解釋了這個概念。您可以使用中止腳本Ctrl - C

#!/usr/bin/env python 
import Queue 
import random 
import threading 
import time 

def main_thread(): 
    """Our main loop in the main thread. 

    It receives the values via a Queue instance which it passes on to the 
    other threads on thread start-up. 
    """ 
    queue = Queue.Queue() 

    thread = threading.Thread(target=run_in_other_thread, 
           args=(queue,)) 
    thread.daemon = True # so you can quit the demo program easily :) 
    thread.start() 

    while True: 
     val = queue.get() 
     print "from main-thread", val 

def run_in_other_thread(queue): 
    """Our worker thread. 

    It passes it's generated values on the the main-thread by just 
    putting them into the `Queue` instance it got on start-up. 
    """ 
    while True: 
     queue.put(random.random()) 
     time.sleep(1) 

if __name__ == '__main__': 
    main_thread() 
+0

謝謝你的迴應。不幸的是,我不能這樣設計我的代碼:我必須在主線程上運行一個eventlet.wsgi.server()。這個運行阻塞主線程的服務器。因爲沒有事件循環,所以我被卡住了。 –

+0

@MrBonjour好的。請修改您的問題以包含所有相關信息。 –

+0

是的,我其實有點迷路。我試圖實現你的例子的派生。這很接近,但由於eventlet,我試圖從同一個線程調用我的套接字objet。我會修改我的問題,因爲我認爲你可以通過他的事件循環在線程中重新傳輸數據。但在這種情況下並不存在。 –

相關問題