在 Python 中,人们习惯于做
def runTaskInNonEDT():
pass
tRunTask = threading.Thread( target = runTaskInNonEDT )
tRunTask.start()
在 Jython 中,我发现如果我想向 EDT 提交方法,我必须去
def makeRunnableClass():
class RunnableClass( Runnable ):
def run( rSelf ):
pass
return RunnableClass
SwingUtilities.invokeAndWait( makeRunnableClass()() )
显然你有关于传递参数等的所有伴随问题。我只是想知道是否可能有一种更快捷、更 Pythonesque 的方式来向 EDT 提交方法?
@lvc
谢谢......是的,事实上我明白了......事实上成语
def makeSthgClass():
class SthgClass():
pass
return SthgClass
是我习惯性地使用的一种,只是为了停止使用一次性子类实例的类名来混淆命名空间。
事实上,我有一些事情可以减轻任务
def runToMessageTree( self, method, *args, **kvargs ):
if SwingUtilities.isEventDispatchThread():
method( *args, **kvargs )
else:
def makeRunnableClass():
class RunnableClass( Runnable ):
def run( self ):
method( *args, **kvargs )
return RunnableClass
SwingUtilities.invokeAndWait( makeRunnableClass()() )
所以你可以去
def doSthg():
pass
self.runToMessageTree( doSthg )
...但它没有任何令人满意的 Pythonic 风格。
之后:
class EDTWorkerThread( WorkerThread ):
def __init__( ewt_self, name ):
super( EDTWorkerThread, ewt_self ).__init__( name )
class EDTWorker( SwingWorker ):
def doInBackground(self ):
check_event_thread( False )
while True:
method_call_elements = ewt_self.input_queue.get()
if method_call_elements is None: # "poison pill"
break
self.super__publish( [ method_call_elements ])
ewt_self.input_queue.task_done()
return
def process( self, chunks ):
check_event_thread( True )
for chunk in chunks:
assert type( chunk ) is list
assert chunk # i.e. must have at least one element!
# check that first item is callable
assert hasattr( chunk[ 0 ], "__call__" )
method_call_elements = chunk
method_args = method_call_elements[ 1 : ]
method_call_elements[ 0 ]( *method_args )
ewt_self.input_queue.task_done()
ewt_self.swing_worker = EDTWorker()
def run( self ):
self.swing_worker.execute()
ẀorkerThread 是一个非常简单、经典的 Python 习语:
class WorkerThread( threading.Thread ):
def __init__( self, *args, **kvargs ):
threading.Thread.__init__( self, *args, **kvargs )
self.input_queue = Queue()
def send( self, item ):
assert type( item ) is list
assert item # i.e. must have at least one element!
# check that first item is callable
assert hasattr( item[ 0 ], "__call__" )
self.input_queue.put( item )
def close( self ):
self.input_queue.put( None )
self.input_queue.join()
def run( self ):
while True:
method_call_elements = self.input_queue.get()
if method_call_elements is None: # "poison pill"
break
method_args = method_call_elements[ 1 : ]
method_call_elements[ 0 ]( *method_args )
self.input_queue.task_done()
self.input_queue.task_done()
return
所以你提交一个方法,然后是可选的 args ...然后这个方法最终在 EDT 中运行,使用有问题的 args。无需创建 Runnables...
当然,另一种可能性是从 SwingWorker 子类化......然后你不会有这种稍微麻烦的“双队列”安排(即 WorkerThread 队列和 EDT 自己的队列,它传递给 process())......但是那么你必须在doInBackground中有一个相当不雅的循环(使用sleep())......
会对人们的意见感兴趣