【问题标题】:Gtk non blocking calls solution?Gtk非阻塞调用解决方案?
【发布时间】:2014-10-30 17:54:42
【问题描述】:

大家好,我在 python 中编写 Gtk+ GUI 应用程序,它使用 onvif 播放视频和移动相机我在应用程序中对 SOAP 服务使用异步调用。但是发生的情况是,当我按下一个用于移动相机视频的按钮时,视频会挂起一秒钟然后按下按钮就可以了,但是当它释放时它又挂了。

Onvif 连续移动类

class ContinuousMove(threading.Thread):
    def __init__(self,onvif_service):
        threading.Thread.__init__(self)
        self.start()
        self.onvif_service=onvif_service
        self.position=self.onvif_service.get_client().factory.create('ns4:PTZVector')
        self.profileToken=self.onvif_service.get_client().factory.create('ns4:ReferenceToken')
        self.speed=self.onvif_service.get_client().factory.create('ns4:PTZSpeed')
        self.timeout=self.onvif_service.get_client().factory.create('ns4:Timeout')
        self.executor=concurrent.futures.ThreadPoolExecutor(max_workers=1)


    def move(self,x,y,zoom):
        future = self.executor.submit(self.__move__,x,y,zoom)
    def __move__(self,x,y,zoom):

       self.position.PanTilt._x=x
       self.position.PanTilt._y=y
       self.position.Zoom._x=zoom

       self.profileToken='media_profile1'

       self.onvif_service.get_client().service.ContinuousMove(self.profileToken,self.position)

正如您在此处看到的,我使用 conncurent.future 模块及其类 ThreadPoolExecutor 进行异步调用

接下来我在扩展 Gtk.Window 的播放器类中创建 ContinuousMove 类的实例 然后我创建按钮并设置事件回调。

    class player(Gtk.Window):
        #bunch of functions
    def __init__(self):
        Gtk.Window.__init__(self):
        self.gui_init()
        self.camera=ContinuousMove(onvif_service)
        self.player=Player(self.previewArea)#class which constructs gstreamer pipeline and renders it on previewArea

    def gui_init(self):
        self.previewArea=Gtk.RenderArea()
        self.buttonDown=Gtk.Button("DOWN")
        self.buttonDown.connect("pressed",self.on_down_pressed)
    
    def on_down_pressed(self,btn):
    #instance of ContinuousMove
        self.Camera.move(0,-0.1,0)

app=player()
app.show_all()
Gtk.main()

如果您能指出我在这里做错了什么以及视频挂起的原因,我将不胜感激。

PS:

没有粘贴整个代码,因为它是巨大的我希望你能从中理解问题。

编辑:

我添加了我的 Player 对象和 RenderArea 对象的 init,因为我认为它与这个问题有关。 我初始化 Player 对象并将其发送给 RenderArea,以便它可以向其渲染视频。 现在的问题是按钮小部件能否以某种方式阻止 RenderArea 小部件?

我将详细解释发生了什么。例如,当我按下向下按钮时,它会冻结视频一秒钟,看起来好像跳过了几帧。尝试了几乎所有方法,但似乎没有任何效果。问题不是 RenderArea 也不是 Gstreamer 问题是移动方法和/或按钮按下事件。

【问题讨论】:

  • self.Camera 是如何设置的? ContinuousMove()线程什么时候启动?
  • 为避免进一步搜索,请创建a minimal complete code example that demonstrates your issue:使代码可按原样运行,删除所有不相关的代码(如果删除代码后问题仍然存在,则它是不相关的),替换阻塞调用使用存根(例如,time.sleep(10) 而不是发出网络请求或使用 time.sleep(1) 并打印 time.time() 值而不是播放视频)等。
  • 对于第一个问题检查上面的编辑。我会试试看,这个问题困扰了我几天,它不是那么大,但我希望每时每刻都能流畅地播放视频。我找到了名为 Winpdb 的应用程序用于调试,但问题是它适用于 python 2.7。我想知道python3有什么好的调试工具,这样我就可以追踪按下按钮时会发生什么。

标签: python python-3.x gtk3


【解决方案1】:

on_down_pressed() 看起来像一个事件处理程序。如果它阻塞,则 GUI“冻结”(不响应)。

with-statement 在退出时调用executor.shutdown(wait=True) 阻塞该方法。 为避免在 Camera.move() 方法中被阻塞,请将 ThreadPoolExecutor() 的创建移动到 __init__() 并仅调用不会在那里阻塞的 executor.submit()

【讨论】:

  • 试过了,但当我尝试移动相机时仍然挂起。有关更多信息,请参阅编辑
  • @user3820641: move(self,x,y,zoom) 方法仍在您的代码中阻塞。
  • 抱歉,这与我的应用程序无关,这是我调用 ContinuousMove 时出现的某种 onvif 错误
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-07-20
  • 2013-10-29
  • 1970-01-01
  • 1970-01-01
  • 2014-03-23
相关资源
最近更新 更多