在Jython中,是否有向EDT提交方法的Pythonesque方法?

在Jython中,是否有向EDT提交方法的Pythonesque方法?,python,multithreading,jython,event-dispatch-thread,Python,Multithreading,Jython,Event Dispatch Thread,在Python中,人们习惯于这样做 def runTaskInNonEDT(): pass tRunTask = threading.Thread( target = runTaskInNonEDT ) tRunTask.start() 在Jython中,我发现如果我想向EDT提交一个方法,我必须去 def makeRunnableClass(): class RunnableClass( Runnable ): def run( rSelf ): pass r

在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()() )
很明显,你会遇到所有关于传递参数的问题,等等。 我只是想知道是否有一种更快捷、更具Python风格的方式向EDT提交方法

@lvc

谢谢。。。是的,事实上我明白了。。。其实这个成语

def makeSthgClass():
  class SthgClass():
    pass
  return SthgClass
我习惯性地使用它来停止用一次性子类实例的类名混乱名称空间

事实上,我有sthg来减轻这项任务

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 )
。。。但这并没有什么令人满意的

后来:

  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
所以您提交了一个方法,后跟可选参数。。。然后,这个方法最终在EDT中运行,使用有问题的参数。不必创建任何可运行项

当然,另一种可能是从SwingWorker中派生子类。。。这样您就不会有这种稍微麻烦的“双队列”安排(即WorkerThread队列和EDT自己的队列,它将传递到process())。。。但是,在doInBackground中必须有一个相当不雅观的循环(使用sleep())


会对人们的观点感兴趣

需要意识到的主要事情是
SwingUtilities.invokeAndWait
需要一个单一方法接口的实例,因为Java没有一流的函数。如果不为该功能使用除
SwingUtilities
之外的其他工具,并且使用更具python风格的接口,则无法避免该位

如果您一心想使用那个特定的API,您仍然可以避免使用包装器函数。只要做:

class RunnableClass(Runnable):
    def run(self):
       pass

SwingUtilities.invokeAndWait(RunnableClass())
使用包装器函数的唯一原因是能够使用pass-in函数在
run
中使用闭包进行调用;您仍然可以通过将函数传递到
RunnableClass.\uuuu init\uuuu
并存储它来实现这一点:

class RunnableClass(Runnable):
    def __init__(self, func):
       self._func = func

    def run(self):
       self._func()
请注意,
func
不应将
self
作为第一个参数-因为它是实例上的属性,而不是类上的属性,所以不会将其视为方法

根据您的编辑-将
func
传递到
RunnableClass.\uuuu init\uuu
的目的是它不再需要是一个一次性子类-您不需要为要运行的每个func都使用
Runnable
的一个子类,只需要一个
RunnableClass
实例。该类本身是一个从Python习惯用法到Java习惯用法的通用适配器,因此您不需要围绕它使用函数来完成相同的工作

这意味着您的
runToMessageTree
可以如下所示:

def runToMessageTree(self, method, *args, **kwargs):
    if SwingUtilities.isEventDispatchThread():
       method(*args, **kwargs)
    else:
       SwingUtilities.invokeAndWait(RunnableClass(method, *args, **kwargs))

当你编辑你的问题时,即使你在其中说@person,它实际上也不会通知那个人——通常的做法是更新它,然后在他们的答案上发表评论(或者在他们评论过的地方发表@person评论),说你已经更新了它。。。。话虽如此,我还是去做了同样的事情。请看我的最新答案。谢谢。是的,这是一个巧妙的技术,很好的pythonic。我想到的一件非常轻微的事情是,它仍然涉及到创建和提交Runnable。我想到的另一个选择是拥有一个(python)线程子类、一个封装的(python)队列和一个(Java)SwingWorker。。。工作非常好,我不知道性能的提高,如果有的话。已输入上述代码,欢迎发表任何意见