【问题标题】:How do I go about not freezing a GTK button that processes information after clicking it?如何在单击后不冻结处理信息的 GTK 按钮?
【发布时间】:2012-12-17 01:33:01
【问题描述】:

我猜我需要做线程,但在我教自己一些不好的做法之前,我想确保我以正确的方式去做。

基本上,我有一个“聊天”应用程序,可以告诉它监听或 ping 收件人的 ip 地址:端口(在我目前的情况下为 127.0.0.1:1300)。当我打开我的应用程序两次(第一个监听,第二个发送 ping)时,我选择一个并告诉它监听(这是一个 While 语句,它一直在监听直到它收到一个 ping 消息)和另一个会ping通它。它效果很好!

问题是,当我单击“侦听 ping”按钮时,它会进入胶合“向下”模式并“视觉”冻结,但是它将 UDP 数据包消息打印到控制台,所以我知道它实际上并没有冻结。所以我的问题是如何做到这一点,以便我可以单击“收听”按钮并让它“收听”,同时有一个“工作”取消按钮,以便用户可以在处理时间过长时取消该过程?

【问题讨论】:

  • 假设我有一个按钮,当我单击该按钮时,它在回调/信号旁边有一个永远的 While() 循环......我该怎么做才能使按钮不存在冻结?它导致用户的错误

标签: c linux ubuntu gtk2


【解决方案1】:

这很可能是因为您使用了同步(阻塞)套接字 IO。您的服务器应用程序很可能会阻塞recv()/read(),这会阻塞您的线程执行,直到一些数据到达;然后它处理数据并返回阻塞状态。因此,您的按钮在按下时由 GTK 呈现。

对于这个问题,基本上有两种通用的方法。第一个是线程。但我建议在更简单的应用程序中反对它;这种方法通常容易出错并且正确实施相当复杂。

第二种方法是异步 IO。首先,您可以使用select()/poll() 函数等待多个 FD 之一发出信号(在诸如“收到数据”、“发送数据”、“接受连接”等事件时)。但是在主循环不是立即可用的 GUI 应用程序中(我不确定 GTK,但在许多 GUI 工具包中都是这种情况),这通常是不可能的。在这种情况下,您可以使用通用异步 IO 库(如 boost asio)。使用 GLIB、IIRC,您可以为套接字交互创建通道 (g_io_channel_unix_new()),然后为它们分配回调 (g_io_add_watch()),当有趣的事情发生时将调用它们。

异步 ​​IO 背后的想法非常简单:您要求操作系统做某事(发送数据、等待事件),然后您做其他重要的事情(GUI 交互等),直到您请求的事情完成(您有能够接收此类事件的通知)。

那么,下面是你接下来可能要学习的内容:

  • select()/poll()(后者一般比较好用)
  • 提升 asio 库
  • GLIB 通道和异步 IO

【讨论】:

  • 太棒了,你让我跳出框框思考,我做了一些在 GTK 之前创建的线程,并在它进入适当的队列时管理工作。例如,我创建了两个 pthread,一个用于不断接收 UDP 数据包并将它们发送到适当的处理器功能,另一个线程在标记为发送的队列中查找数据。
  • 不错!但即使线程一开始似乎更容易实现(并且看起来更明显),我强烈建议研究我提到的异步 IO 方法:)
猜你喜欢
  • 1970-01-01
  • 2013-03-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-05-25
  • 1970-01-01
相关资源
最近更新 更多