最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

multithreading - Manage Qt Objects events in non-Qt application; threading conflicts and deadlocks - Stack Overflow

programmeradmin0浏览0评论

I have a Qt based library, that manages UDP communication with a device; connection (more like "connection", since it is UDP; I call connection to create the UDP socket and do the bind and first setup of the device), communication/data exchange, disconnection (close/delete UDP sockets).

I have a Qt GUI application that uses this library. Everything works like a charm.

Awfully, the library need to be used in a non-Qt application. I added to the library the creation of a QCoreApplication to start the event loop and be able to manage internal signals/slots (something like this). Things kinda work.

The problem is, I have no control on the non-Qt user app, especially on the use of threads. The user can create my object in the main thread, connect the device in another, disconnect it in a third one. This leads to errors like QSocketNotifier: Socket notifiers cannot be enabled or disabled from another thread. One example is when the user disconnects the device from a different thread, so the socket gets closed/destroyed in a thread different from its parent. To avoid this, I can send a signal, previously connected with QueuedConnection, to the object, so the operation is performed in the object thread.

This leads to another problem; the user calls for a disconnection, but doesn't know when the disconnection will actually happen. Ideally, the disconnection call should be "synchronous", and exits when the disconnection is done. Ideally, I should wait for the disconnection from the object (called with signal) and then return. But how to do this? And how to do this without deadlocking the program? (e.g. slot won't be executed because current thread is waiting)

Any hint will be appreciated!

I have a Qt based library, that manages UDP communication with a device; connection (more like "connection", since it is UDP; I call connection to create the UDP socket and do the bind and first setup of the device), communication/data exchange, disconnection (close/delete UDP sockets).

I have a Qt GUI application that uses this library. Everything works like a charm.

Awfully, the library need to be used in a non-Qt application. I added to the library the creation of a QCoreApplication to start the event loop and be able to manage internal signals/slots (something like this). Things kinda work.

The problem is, I have no control on the non-Qt user app, especially on the use of threads. The user can create my object in the main thread, connect the device in another, disconnect it in a third one. This leads to errors like QSocketNotifier: Socket notifiers cannot be enabled or disabled from another thread. One example is when the user disconnects the device from a different thread, so the socket gets closed/destroyed in a thread different from its parent. To avoid this, I can send a signal, previously connected with QueuedConnection, to the object, so the operation is performed in the object thread.

This leads to another problem; the user calls for a disconnection, but doesn't know when the disconnection will actually happen. Ideally, the disconnection call should be "synchronous", and exits when the disconnection is done. Ideally, I should wait for the disconnection from the object (called with signal) and then return. But how to do this? And how to do this without deadlocking the program? (e.g. slot won't be executed because current thread is waiting)

Any hint will be appreciated!

Share Improve this question asked Feb 6 at 15:14 il_mixil_mix 5719 silver badges26 bronze badges 4
  • Does the third-party program at least guarantee that only one thread will be making calls on a given object at a time? e.g. that each of your Qt objects is accessible by a single user-thread and won't be accessed by any of the other ones, at least not without some kind of serialization/handoff between them? – Jeremy Friesner Commented Feb 6 at 18:25
  • Note that Qt does have a BlockingQueuedConnection signal-connection type, but you're right that using it risks the possibility of deadlock if you aren't very careful about avoid cycles in your signalling patterns. – Jeremy Friesner Commented Feb 6 at 19:12
  • I can't be sure regarding how the user will play with their threads. Multiple threads can access the device. A reasonable example can be the user spawning a thread to connect to the device (takes a while), and when the device is ready the thread exits and informs the GUI of the outcome. Then another thread is created to manage the disconnection. So there can be multiple threads calling the object. Yet, I suppose it is safe to suppose they won't do concurrent call. Anyway, this will lead to different kind of errors. – il_mix Commented 2 days ago
  • I tried the BlockingQueuedConnection in a non-Qt application I use as test bench, and indeed generated a deadlock (Qt itself prints an error when it occurs) – il_mix Commented 2 days ago
Add a comment  | 

1 Answer 1

Reset to default 0

One terribly ugly yet possible solution would be to add in a "front end" to the library: a QThread whose sole job is to serve as a proxy between the Qt-library code on one side, and the non-Qt application's threads on the other. Since all the handling would go through this single QThread, Qt's signals would work as expected, while the application's threads would use a custom front-end API of some sort to interface with the proxy-QThread.

So, for example:

  • To send a packet, an application-thread would call a method on the front-end API, which would place the packet into a message-queue of some sort, and then wake up the QThread (maybe via a call to QCoreApplication::postEvent(theThread, ...)) so it can asynchronously drain that message-queue and call the necessary Qt-library-functions later on.

  • After receiving a packet, the QThread would need to add the packet into a separate "replies" message queue, and then somehow notify the user-application to check the replies-message-queue to receive the packet. (Exactly how that could be done depends on how the user-application is implemented, but most programming frameworks have some way to do it)

发布评论

评论列表(0)

  1. 暂无评论