How do I go about not freezing a GTK button that processes information after clicking it?

StackOverflow https://stackoverflow.com/questions/13907278

  •  09-12-2021
  •  | 
  •  

Frage

I'm guessing I'm going to need to do threading but before I teach myself some bad practices I wanted to make sure I'm going about this the correct way.

Basically I have a "chat" application that can be told to listen or ping the recipients' ip address:port (in my current case just 127.0.0.1:1300). When I open up my application twice (the first one to listen, the second to send a ping) I pick one and tell it to listen(Which is a While statement that just constantly listens until it gets a ping message) and the other one will ping it. It works just peachy!

The problem is when I click the "Listen for ping" button it will go into a glued "down" mode and freeze up "visually" however it prints the UDP packet message to the console so i know its not actually frozen. So my question is how to I make it so I can click the "Listen" button and have it "listen" while at the same time have a "working" cancel button so the user can cancel the process if its taking too long?

War es hilfreich?

Lösung

This most likely happens because you use synchronous (blocking) socket IO. Your server application most likely blocks on the recv()/read(), which blocks your thread's execution until some data arrives; it then processes the data and returns to blocked state. Hence, your button is rendered by GTK as pushed.

There are, basically, two generic approaches to this problem. The first one is threading. But I would recommend against it in the simpler applications; this approach is generally error-prone and pretty complicated to implement properly.

The second approach is asynchronous IO. First, you may use select()/poll() functions to wait for one of multiple FDs to be signalled (on such events as 'data received', 'data sent', 'connection accepted'). But in a GUI application where the main loop is not immediately available (I'm not sure about GTK, but this is the case in many GUI toolkits), this is usually impossible. In such cases, you may use generic asynchronous IO libraries (like boost asio). With GLIB, IIRC, you can create channels for socket interaction (g_io_channel_unix_new()) and then assign callbacks to them (g_io_add_watch()) which will be called when something interesting happens.

The idea behind asynchronous IO is pretty simple: you ask the OS to do something (send data, wait for events) and then you do other important things (GUI interaction, etc.) until something you requested is done (you have to be able to receive notifications of such events).

So, here's what you may want to study next:

  • select()/poll() (the latter is generally easier to use)
  • boost asio library
  • GLIB channels and asynchronous IO
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top