2011-12-16 53 views
3

我有,爲了方便起見(我重用現有的代碼)已經被分成兩個不同的線程的應用程序:觸發事件從另一個線程

  • 一個線程運行扭曲反應器
  • 另一個線程運行交互式菜單

我想從交互式菜單中執行的一件事是與反應堆進行交互。一旦用戶給出了特定的命令,我想觸發一個扭曲的事件。這裏是我的代碼非常簡化的版本:

from twisted.spread     import pb 
from twisted.internet     import reactor 
import threading 

class TaskGatewaySupport(): 

    def __init__(self): 
     self.object = None 
     self.factory = pb.PBClientFactory() 
     self.connector = None 

    def gotObject(self, object): 
     print 'gotObject > %s' % object 
     self.object = object 
     return object 

    def gotData(self, data): 
     return data 

    def gotNoObject(self, reason): 
     print 'gotNoObject > no object: %s' % reason 

    def connect(self, task_gateway_host = '127.0.0.1', task_gateway_pb_port = 8889): 
     print 'Connecting to %s:%s' % (task_gateway_host, task_gateway_pb_port) 
     self.connector=reactor.connectTCP(task_gateway_host, task_gateway_pb_port, self.factory) 
     d = self.factory.getRootObject() 
     d.addCallbacks(self.gotObject, self.gotNoObject) 
     return d 

def Menu(task_gateway_support): 
    while True: 
     print ''' 

     A) Connect 

     ''' 
     choice = raw_input('Option > ') 
     if choice == 'A' : task_gateway_support.connect() 
     else    : print "ERR: command not yet supported" 

def version1(): 
    task_gateway_support = TaskGatewaySupport() 
    thread = threading.Thread(target = Menu, args = (task_gateway_support,)) 
    thread.start() 
    reactor.run() 

def version2(): 
    task_gateway_support = TaskGatewaySupport() 
    d = task_gateway_support.connect() 
    reactor.run() 

if __name__ == '__main__': 
    version1() 

正如你所看到的,我出兩個不同的版本:

  • VERSION1是一個我想運行,但它不會
  • 版本2只有一個線程,它不是交互

運行版本2將給這個結果:

Connecting to 127.0.0.1:8889 
gotObject > <twisted.spread.pb.RemoteReference instance at 0x88e734c> 

這就是我期待的。

運行VERSION1會給這樣的:

 A) Connect 


Option > A 
Connecting to 127.0.0.1:8889 


     A) Connect 


Option > ^CgotNoObject > no object: [Failure instance: Traceback (failure with no frames): <class 'twisted.internet.error.ConnectError'>: An error occurred while connecting: [Failure instance: Traceback (failure with no frames): <class 'twisted.internet.error.ConnectionLost'>: Connection to the other side was lost in a non-clean fashion: Connection lost. 
]. 
] 

什麼,我這裏做的是選擇選項A,並且由於沒有任何反應,我按^ C,顯示錯誤消息。

我認爲出現的問題是因爲我在兩個不同的線程中共享一個對象,並且我試圖從非扭曲的線程中觸發扭曲的事件。我希望,由於物體是共享的,反應堆會意識到任何物體都會變形。

所以我的主要問題是:如何從另一個線程觸發扭曲事件?

回答

0

我實際上用Twisted自己遇到了這個問題。幸運的是,經過大量的谷歌搜索後,我能夠想出這個答案,實際上效果很好! -

def my_function(s): 
    do_something_with_s 

class GetCommands(): 
def start(self, callable): 
    self.callable = callable 
    self.startReceiving() 

def startReceiving(self, s = ''): 
    self.callable(s) 
    if s != 'exit': 
     threads.deferToThread(raw_input,' >>> ').addCallback(self.startReceiving) 

然後在主 -

getCmds = GetCommands() 
reactor.callWhenRunning(getCmds.start, my_function) 

reactor.listenTCP(PORT, factory) 
reactor.run() 
+0

見讓 - 保羅的回答了問題較少的方式來獲取用戶輸入。這個策略有一個問題:如果`raw_input`正在一個線程中運行,那麼在反應堆運行時沒有安全的方法來停止它;您必須等待用戶輸入最終命令。 – Glyph 2013-06-28 23:18:02

相關問題