Skip to content
  • 1 Votes
    3 Posts
    253 Views
    S

    With normal caveats regarding "threads" (web workers in web parlance) you could just run your data simulation in a thread and then use the main thread to update your VBO and render.

  • 0 Votes
    3 Posts
    662 Views
    M

    @jsulm said in QJSEngine crashes when used in multithreading program:

    @mdma2 said in QJSEngine crashes when used in multithreading program:

    I've found a bugreport that is similar to my problem

    Did you read the comments there? Especially this one: "You have to create the engine in the same thread as the one where you are using it. And you cannot create your function in one thread and call it in a different one.".
    You can't make it thread safe without changing its implementation. Is there a reason why you wantr to use it from different threads?

    Yeah, there's need of evaluating JS code and accessing a QJSEngine object from different threads because of my program specificity. However there should be workaround to make it possible, like switching to the engine's thread before accessing to QJSEngine object. All I have found is using signal/slot system or QMetaObject:: invokeMethod (the last one is provided in the bugreport) to do that, but none of them work at the test code, I don't know why.

  • 0 Votes
    10 Posts
    3k Views
    piervalliP

    @aljoachim
    If you set journal_mode = WAL we can do the query in multithreading . There are not restrictions.
    In my solution when the secondary need an update or insert send the request of main thread and wait the response

  • 0 Votes
    5 Posts
    768 Views
    CJhaC

    @JonB It is InheritPriority It was a mistake from my side. Yes, I think you are right, I will have to go to the caller for that. Thanks!

  • 0 Votes
    1 Posts
    228 Views
    No one has replied
  • 0 Votes
    2 Posts
    926 Views
    JonBJ

    @alan02011114
    I don't understand what your question is. As the error message tells you, your slot requires a dfreceived/second position argument and you are not supplying it in your lambda so you get the error.

  • 0 Votes
    6 Posts
    717 Views
    Vivek_AV

    @Christian-Ehrlicher @JonB Solved . By creating a seperate worker.cpp file and connected RTLSClient signal to worker slot, now data is inserting to mongodb very fast without freezing GUI.
    Thanks ..

  • 0 Votes
    6 Posts
    1k Views
    S

    Thanks a lot for these answers.

    To summarize:

    Solution 1 from the original post is confusing and therefore not good. Solution 2 from the original post is much better. An alternative would be to disable tracking of the slider, so the image only gets updated on mouse release.

    Disable the tracking would be the easiest thing to do, but it is not very flexible. There are two main problems for me:

    I also have spin boxes in the dialog, which also change the image, and I do not want to disable the arrow-up and arrow-down support for these spin boxes because that seems a bit strange. I do not know the speed of the target system, so anyway I prefer to use threads to make sure the UI stays reactive.

    Therefore, I think I will go for solution 2.

    Stays the question of how to implement this.

    Did you try to see the hot paths of your application with a tool like hotspot ?

    No.

    Beside that, what exactly takes that long in your application ?
    From a quick look at your code, you likely do too much in your paint event.
    You are creating a new QImage every time paintEvent is called, why not create it once on resize and then just repaint on top of it.

    Indeed, the paint event (and also the rest of the code) is not speed-optimized at all. My plan was:

    Define which behaviour I want. (That is done now, thanks to you!) Decide which threading technologies to use. (To be done.) Optimize the individual parts where necessary. (To be done.)

    But I remember that, when once ago on a pretty fast computer and with a small widget size, I measured the old synchronous code, the paint event took 360 ms, of which 330 ms were the image rendering algorithm, which has therefore the biggest problem.

    Also, I will look into your suggestion to keep always a QImage in memory, so that it is not allocated again on each paint event. (Also, I have heard somewhere that Qt itself does the same thing.)

    you might want to check out the Mandelbrot example.

    Yes, indeed, the current multithread code is based on the Mandelbrot example.

    One other possibility is to update the content of the image when something changes and just paint the updated image once that is done.

    Indeed, I'm using yet an image cache, so there is no unnecessary rendering of the image.

    Of course, only you know why this thing takes this long and whether anything can be done to reduce it.

    That's the most interesting question. The algorithm calculates each pixel independently: Perfect for splitting the work into as many threads as the count of virtual cores of the target computer. And probably, the algorithm itself can also be optimized.

    How could this work? I have no experience in multithreading. Doing it manually with QThread seems therefore complicated and error-prone to me. Could I query the number of virtual cores, and then use QtConcurrent::run() as many times as virtual cores are available, each call with just a fraction of the rendering image? Would this scale well? (As I'm developing a library, I have no knowledge about what other threads the application developer will use in his own code.)

    it can't be done as a gradual thing.

    Actually, probably in can be done as a gradual thing. Maybe allocate a QImage in full-resolution size. Then, calculate pixel (0, 0) and set this color for pixel (0, 0), but also for (0, 1), (1, 0) and (1, 1). And so on, until the QImage is complete. Do a paint event with this low-resolution image. Do a new run and calculate (0, 1), (1, 0) and (1, 1) exactly. And so on, until the QImage is complete. Then, do a new paint event with the full-resolution image. This idea could also be adapted to work with more than only two steps. Do you think this is a good idea?

  • 0 Votes
    6 Posts
    644 Views
    JKSHJ

    @CJha said in How to use full processing power available to do calculations?:

    If I use more threads by using QtConcurrent::mapped() or QThreadPool from inside a non-GUI thread, will it use this non-GUI calling thread as well? To make my point more clear: Let's say I create a thread called A and based on the number of cores my CPU has I have thread B, C and D available. After my thread A calls either QtConcurrent::mapped() or QThreadPool to start the calculation it has nothing more to do till the calculation finishes, so will it wait idle while my calculations are running in other threads or will QtConcurrent::mapped() or QThreadPool include thread A along with B, C and D to do the calculations?

    We need to know: How do you create thread A?

    QtConcurrent uses the global QThreadPool behind the scenes. If thread A is not part of the pool, then it won't be used by the pool to do calculations when it is idle.

    Is there any way I could run a single loop (major loop of my calculation) in multiple threads with different data sets without using QtConcurrent::run()? QtConcurrent::mapped() will not work as it has requirements that there should be a return type which is not always the case with my calculations. QThreadPool, QRunnable and especially QThreadPool::globalInstance() documentation is not enough for me to make this judgement.

    QtConcurrent::map() (not mapped()!) does not return any values. You can interface with it using QFuture<void>.

    See https://doc.qt.io/qt-5/qtconcurrentmap.html#concurrent-map

    Finally, is there a better/simpler approach to solving this problem?

    Experiment with QtConcurrent::map() and see if it suits your application.

    NOTE: I have placed the same question in Stack Overflow as well.

    As a courtesy to other users, please link your duplicate questions to each other. This way, people can see if your question has been resolved and get the answer too

  • 0 Votes
    7 Posts
    1k Views
    SGaistS

    Looks like you are re-implementing tools that already exist for that purpose. Was tmux/xpanes considered ?

    In any case, before doing any threading, you should have a proper encapsulation for your connection and command sending. Once you have that you can start thinking about threads or maybe use QtConcurrent. It looks like you rather have lists of commands to send to machines. A bit like what ansible manages for you with its playbook.

  • 0 Votes
    5 Posts
    2k Views
    A

    I got it fixed, thanks to @Christian-Ehrlicher!

    I almost did not try your suggestion because I thought I knew very well where the warning comes from.

    But it turned out that I had missed a setQuery() call that was lacking its second parameter (the database connection to use).

  • 0 Votes
    4 Posts
    694 Views
    SGaistS

    Hi,

    In your class declaration.

    Note that this is basic C++. If you do not know that, I highly encourage you to first improve your C++ knowledge before going further.

  • 0 Votes
    5 Posts
    2k Views
    Pablo J. RoginaP

    @Alphy said in same serial in multiple threads giving error:

    it is working fine.

    So please don't forget to mark your post as solved!

  • 0 Votes
    3 Posts
    2k Views
    6thC6

    I'd be careful just because of my own assumptions / experience, it sounds like you're setting up a landmine for later, I don't know because I just skimmed your issues, I can't tell enough for a proper context but I can recall the bug report that I found when I did.

    You might find this useful too: https://bugreports.qt.io/browse/QTBUG-43230

    Ulf Hermann added a comment - 18 Mar '19 9:19 PM
    Note that exposing objects that live in a different thread as the QML engine via context properties is dangerous to begin with. You cannot safely access properties or call methods of such objects from QML. I really recommend proxying the signals through a separate object that lives in the engine thread.

    Ulf Hermann added a comment - 30 Apr '19 10:02 PM
    The bad idea is not actually the connection. The fact that the connection behaves in the way described here is just the consequence of the fact that you're exposing an object from a different thread. The QML language has no concept of threads (besides WorkerScript, but that is a different beast), so exposing the C++ threading model to it via context properties is a bad idea. The engine does not magically provide thread safety for otherwise unsafe operations and it needs to inspect the objects given to it as context properties.
    Please make sure everything you expose to a particular engine lives in the same thread. Otherwise all bets are off anyway.

  • 0 Votes
    2 Posts
    1k Views
    kshegunovK

    None of the above. Pool your TCP connections on top of a few threads, and independently pool your few database connections on top of another set of threads. Make the actual queries asynchronous by queuing them through the tread pool.
    The solution's rather complex, though, and 1000 connections ain't that much, so you may be able to get away with a single thread for the TCP stack and a single thread for the SQL stack.

  • 0 Votes
    12 Posts
    2k Views
    L

    Just replying to say I got it working 100% as I expected, while still registering my object as a singleton!
    I just added a Connections element to my QML code, with the singleton object as its target. Thank you for your help, @mrjj

  • 0 Votes
    11 Posts
    2k Views
    R

    I CUDA not build it unfortunately. CUDA is only supported in Visual Studio for Windows so I guess its back to good old uncle GL ...

  • 0 Votes
    13 Posts
    3k Views
    Matthew11M

    OK as @J.Hilk said:

    @J.Hilk said in Passing custom type pointers between threads via signals and slots cause app to crash:

    are you by any chance exposing those thread-shared custom types directly to qml?

    And:

    @J.Hilk said in Passing custom type pointers between QML and threads via signals and slots cause app to crash:

    I can only tell you that I always ran into trouble when I tried to access/manipulate c++ threaded stuff (directly)via QML.

    Indeed that was causing the crashes. The solution is to create a copy of the resource that is sent from QML and then send a copy of that resource to thread.

    As @J.Hilk suggested Manager object should do the job which is:

    @Matthew11 said in [Passing custom type pointers between QML and threads via signals and slots cause app to crash

    Manager <-> Threads : communicate via signal/slots with QueuedConnection synchronization/locking on the shared resource Manager <-> QML signals and slots or directly from the manager's memory

    Below you can find my working example. This is very similar to the code which I provided in the first post. You send a dispatch from QML to specific Contractor, Contractor then is doing his job and return the result back to QML (sends task with input data scenario). Or you send a dispatch to Contractor to retrieve some data (send task with no input data scenario). ContractorTask is no longer exposed to QML. But pointers are no longer send however it is possible in the C++ domain (across main (Manager) and workers threads with proper locking/synchronization).

    If you want to feel how it is when app is crashing uncomment the line _taskCopy.setData(_data); from pushTaskToContractor() in Controller.h which disabling the step of making the copy of the resource.

    Thank you all for your help in solving the problem!

    Code:

    //.pro QT += quick CONFIG += c++11 SOURCES += \ Contractor.cpp \ main.cpp RESOURCES += qml.qrc HEADERS += \ Contractor.h \ ContractorTask.h \ Controller.h // Contractor.h #ifndef CONTRACTOR_H #define CONTRACTOR_H #include <QObject> #include <ContractorTask.h> class Contractor : public QObject { Q_OBJECT public: Contractor(int _ID, QObject* parent = nullptr); int getID() { return ID; } public slots: void executeTask(ContractorTask _task); signals: void finished(); void taskStarted(ContractorTask _task); void taskFinished(ContractorTask _task); private: int ID; }; #endif // CONTRACTOR_H // Contractor.cpp #include "Contractor.h" #include <QDebug> #include <QThread> Contractor::Contractor(int _ID, QObject *parent) : QObject(parent), ID(_ID) {} void Contractor::executeTask(ContractorTask _task) { emit(taskStarted(_task)); if(getID() != _task.getConctractorID()) { qDebug() << "Not mine ID, discarding"; return; } QVariant localData = _task.getData(); switch(_task.getTaskID()) { case 0: // PASS TASK TO C++ TO RETRIEVE DATA { QList<QVariant> _params; _params.append(12.5F); _params.append(14.36F); QVariant _data = _params; _task.setData(_data); qDebug() << "PASS TASK TO C++ TO RETRIEVE DATA"; } break; case 1: // PASS TASK WITH DATA TO C++ AND GET THE SAME DATA BACK IN QML { QList<QVariant> _params; _params = localData.value<QList<QVariant>>(); QList<float> _floats; int counter = 0; for(auto item : _params) { _floats << item.toFloat(); qDebug() << "Getting data in C++ from QML (QList<float>): item =" << counter++ << "value =" << item; } qDebug() << "PASS TASK WITH DATA TO C++ AND GET THE SAME DATA BACK IN QML"; } break; default: { qDebug() << "Oh... I don't have these one :("; } } emit(taskFinished(_task)); } // ContractorTask.h #ifndef CONTRACTORTASK_H #define CONTRACTORTASK_H #include <QVariant> class ContractorTask { public: ContractorTask() : taskID(-1), contractorID(-1), data("") {} int getTaskID() { return taskID; } void setTaskID(int _ID) {taskID = _ID; } int getConctractorID() { return contractorID; } void setContractorID(int _ID) { contractorID = _ID; } QVariant getData() { return data; } void setData(QVariant _data) { data = _data; } private: int taskID; int contractorID; QVariant data; }; Q_DECLARE_METATYPE(ContractorTask) #endif // CONTRACTORTASK_H // Controller.h #ifndef CONTROLLER #define CONTROLLER #include <QObject> #include <QThread> #include <QDebug> #include <Contractor.h> #include <ContractorTask.h> class Controller : public QObject { Q_OBJECT QThread workerThread; public: Controller() { Contractor *worker = new Contractor(0); worker->moveToThread(&workerThread); connect(&workerThread, &QThread::finished, worker, &QObject::deleteLater); connect(this, &Controller::startTask, worker, &Contractor::executeTask); connect(worker, &Contractor::taskStarted, this, &Controller::contractorStartedTask); connect(worker, &Contractor::taskFinished, this, &Controller::contractorFinishedTask); workerThread.start(); } ~Controller() { workerThread.quit(); workerThread.wait(); } signals: void startTask(ContractorTask); void taskStarted(int id, int contractor, QVariant data); void taskEnded(int id, int contractor, QVariant data); public slots: void pushTaskToContractor(int _id, int _contractor, QVariant _data) { // QVariant depends to QML, so make COPY of QVariant CONTENT, before passing it to thread: QList<QVariant> _params; _params = _data.value<QList<QVariant>>(); QVariant _dataToSend = _params; ContractorTask _taskCopy; _taskCopy.setTaskID(_id); _taskCopy.setContractorID(_contractor); _taskCopy.setData(_dataToSend); // Sending local data copy is OK // _taskCopy.setData(_data); // Sending _data (has source in QML) = PROGRAM CRASH!!! emit(startTask(_taskCopy)); } void contractorFinishedTask(ContractorTask _task) { // Passing COPY of ContractorTask to QML: emit(taskEnded(_task.getTaskID(), _task.getConctractorID(), _task.getData())); } void contractorStartedTask(ContractorTask _task) { // Passing COPY of ContractorTask to QML: emit(taskStarted(_task.getTaskID(), _task.getConctractorID(), _task.getData())); } }; #endif // CONTROLLER // main.cpp #include <QGuiApplication> #include <QQmlApplicationEngine> #include <Controller.h> #include <QQmlContext> int main(int argc, char *argv[]) { QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling); QGuiApplication app(argc, argv); Controller TaskController; qRegisterMetaType<ContractorTask>(); QQmlApplicationEngine engine; engine.rootContext()->setContextProperty("TaskController", &TaskController); const QUrl url(QStringLiteral("qrc:/main.qml")); QObject::connect(&engine, &QQmlApplicationEngine::objectCreated, &app, [url](QObject *obj, const QUrl &objUrl) { if (!obj && url == objUrl) QCoreApplication::exit(-1); }, Qt::QueuedConnection); engine.load(url); // Get item from QML, and connect it's signal (startTaskFromQML) to Controller QObject *item = engine.rootObjects().first(); QObject::connect(item, SIGNAL(startTaskFromQML(int, int, QVariant)), &TaskController, SLOT(pushTaskToContractor(int, int, QVariant))); return app.exec(); } // main.qml import QtQuick 2.12 import QtQuick.Controls 2.5 ApplicationWindow { id: root visible: true width: 640 height: 480 title: qsTr("Test") signal startTaskFromQML(int id, int contractor, variant data) property variant _data: 0 Connections { target: TaskController onTaskEnded: console.log("Contractor with ID =", contractor, "finished task with ID = ", id, "and returned result:", data); onTaskStarted: console.log("Contractor with ID =", contractor, "started task with ID = ", id); } Column { id: column anchors.horizontalCenter: parent.horizontalCenter anchors.verticalCenter: parent.verticalCenter Button { id: passAndGet text: qsTr("PASS TASK WITH DATA TO C++ AND GET THE SAME DATA BACK IN QML") anchors.horizontalCenter: parent.horizontalCenter onClicked: { _data= [1.2, 3.4, 5.6, 7.8] for(var i = 0; i < 50; i++) { root.startTaskFromQML(1, 0, _data) } } } Button { id: getData text: qsTr("PASS TASK TO C++ TO RETRIEVE DATA") anchors.horizontalCenter: parent.horizontalCenter onClicked: { _data = 0 root.startTaskFromQML(0, 0, _data) } } } } // qtquickcontrols2.conf [Controls] Style=Material // qml.qrc <RCC> <qresource prefix="/"> <file>main.qml</file> <file>qtquickcontrols2.conf</file> </qresource> </RCC>