I have written a C++ 11 code using asio to send/receive the packets from network. To work with asio, asio::io_service::run() need to be called and the main thread will be waiting in this function.
Now, in one of the applications, I need to develop a Gui for which I need to use Qt 4.8. But for a Qt Gui application, the main thread need to wait in QApplication::exec(). Though Qt has its own libraries to send/receive data from Network, I would like to use the code with asio.
How can I use asio along with Qt?
Without seeing your code.. a high-level generic approach:
Call io_context::run() in a new thread. All async handlers will execute in this thread.
Use a mutex to ensure the data model can be safely shared between ASIO and the GUI. Lock the mutex consistently any time the data is read or updated.
Use Qt signals and slots and/or condition_variable to signal the GUI from ASIO completion handlers whenever the UI needs to be updated. Do not touch the GUI directly from ASIO code, as only the UI thread may update the UI.
Related
I'm using blocking sockets API (waitFor* functions) for sending mail by smtp protocol (it's a DLL modue). All operations are synchronous: connect->waitForConnected(timeout)->login->waitForReadyRead(timeout)->sendMessage->waitForBytesWritten(timeout)->etc.
I'm using blocking API, because QCoreApplication absence is required (DLL used by different apps, incl. non-qt-based). Blocking functions don't require event loop and it works fine.
But how can I make a visual progress for long-term sending mail operations (with big attachment, for example)?
And how can organize callbacks for progress notifications in sendmail DLL?
ps: all blocking waitFor* functions marked as
functions, that may fail randomly on Windows. Consider using the event loop and the readyRead() signal if your software will run on Windows.
Why?
You can definitely have a QApplication instance when using DLLs (it must be QApplication not QCoreApplication since you want a widget-based gui). It integrates into the native message loop of the main thread. Remember that for Qt Gui to run you only need a native event loop - the code doesn't have to be stuck within QCoreApplication::exec. You need an instance of the application, and you need to prime it by invoking exec once, and ensuring that it returns (i.e. by using a zero-timeout timer), but that's all. Past that, the application's main thread's message pump will handle things for you.
Furthermore, to use networking APIs, you don't need to be stuck in the main thread - you can handle them in a separate thread.
Your DLL won't be compatible with console applications that don't run a message pump in the main thread, but then you can cheat: on Windows, and on Windows only, the QCoreApplication and its derived classes can be used in any thread :)
You definitely must either statically link your DLL with Qt, or use a dynamically-linked Qt that was put in a unique namespace. Remember that if the application you link with uses Qt, there are absolutely no guarantees that the Qt they built is binary-compatible with the Qt that you use. Even if it's the same version.
I'm on some c++ mobile product, but I need my apps main thread is still running without any blocking when doing some heavy work on the background thread and run back on main thread. But I realized there is no runOnMainThread/runOnUIThread in c++ thread api. I trying to figure it out the issue and found that need to depend library, or create your own thread event queue. Although it is good, but i am thinking to have a behavior which can runOnUIThread.
How it does not work: the mentioned library creates a timer, installs a SIGALRM signal handler and dispatches queued tasks when signals are fired. This allows tasks being processed on the main thread even when it is busy. However POSIX permits only a small set of async-signal-safe functions to be invoked inside of signal handler. Running arbitrary с++ code inside of signal handler violates that restriction and leaves application in hopelessly doomed state.
After some research and development, I've created a library called NonBlockpp
it is a small c++ library to allow c++ mobile application able to process the heavy and time consuming task on background and back to Main thread again, It’s been tested and fired the main thread event.
It also allow to save the tasks and fire them later, all the task has no blocking each other and thread safety.
How it works:
If you found any query or suggestion, please don't hesitate to raise an issue and we can discuss it together.
The project has rectify from signal to pollEvent due to signal handler might not be safe to use.
Please take a look the new changed.
NonBlockpp
Usage
So, I have a single-threaded application which loads data from a set of file:
QStringList qFiles = QFileDialog::getOpenFileNames(
this,
"Choose Image Files",
"",
"Dicom Files(*.dcm);;All Files(*)"
);
After that I invoke a library which will parse the set of files, since the library invokes OpenGL functions I may not create a new thread for this processing.
Once this processing is done I noticed my application froze for a while.
Using GDB I noticed my Qt Application buffered a lot of Events while the library processed the set of files and then it is processing these events.
I may not invoke QApplication::instance()->processEvents() inside the libary, because it doesnt know Qt(project decision).
Is there way to discard these events? Or is there any other solution to keep my application from freezing?
Move OpenGL Rendering to a Worker Thread
If possible, move your OpenGL rendering to a separate thread. Then you can call your library functions there and not worry about them blocking the event queue.
You should be able to devote your framebuffer to the worker thread and communicate with it using signals and slots just fine.
Alternative: Implement Progress Callbacks
Alternatively you could see if the library has any callbacks. If you have source available, you could implement your own during long-running operations.
I have a QThread that reads from a socket and sends a signal (QT signal) when there are any data available.
This would be easy with blocking read(2), but i need to be able to stop the thread from outside without waiting for too long.
If I were using pthread I would use pselect and pthread_kill(thread_id, some_signal), but QThread doesn't
seem to have any similar methods. And adding a dependcy on pthread to this project doesn't seem to elegant.
I also don't want to use the other ugly methods like constantly trying to read from the socket with some relatively small timeout.
Edit: The sockets are not TCP, but bluetooth L2CAP.
A not too elegant, but simple and working solution:
Create a pipe and let select wait for either the pipe or my socket. This way I can stop the wait anytime by writing something to the pipe.
Instead of dealing with the threading yourself you can use the asynchronous interface of QTcpSocket. Check out the Fortune Client example.
You can send a signal to the terminate() slot of your QThread. This will stop your thread according to OS scheduling policies.
I have a Qt/C++ application, with the usual GUI thread, and a network thread. The network thread is using an external library, which has its own select() based event loop... so the network thread isn't using Qt's event system.
At the moment, the network thread just emit()s signals when various events occur, such as a successful connection. I think this works okay, as the signals/slots mechanism posts the signals correctly for the GUI thread.
Now, I need for the network thread to be able to call the GUI thread to ask questions. For example, the network thread may require the GUI thread to request put up a dialog, to request a password.
Does anyone know a suitable mechanism for doing this?
My current best idea is to have the network thread wait using a QWaitCondition, after emitting an object (emit passwordRequestedEvent(passwordRequest);. The passwordRequest object would have a handle on the particular QWaitCondition, and so can signal it when a decision has been made..
Is this sort of thing sensible? or is there another option?
Using signals to send messages between threads is fine, if you don't like using the Condition Variable, then you can send signals in both directions in a more-or-less asynchronous manner: this might be a better option if you want to continue processing network stuff while you wait for a reply from the GUI.