Я столкнулся с довольно странной проблемой с QtConcurrent
, в основном из-за странных желаний программирования, может быть, это просто проблема XY, но ...
Итак, мой код пытается общаться с базой данных, на самом деле код бэкэнда (на Qt, да). Он должен работать быстро и обрабатывать некоторые запросы, поэтому мне нужен пул потоков. Как общеизвестный факт, я предполагаю, что установление соединения само по себе является очень трудоемкой операцией, поэтому существует необходимость в постоянных соединениях с базой данных, приводящих к постоянным потокам (QSqlDatabase
нельзя перемещать между потоками). Также вполне естественно хотеть обрабатывать асинхронные запросы, в результате чего возникает необходимость в простом способе их передачи постоянным потокам.
Ничего слишком сложного, допустим, что в такой форме уже есть какой-то шаблон. ..
// That's what I want for now
QFuture<int> res = workers[i]->async(param1, param2);
// OR
// That's what I DO NOT want to get
workers[i]->async(param1, param2, [](QFuture<int> res) { // QFuture to pass exceptions
// callback here
});
Это можно сделать наверняка. Почему не std::future
? Что ж, гораздо проще использовать QFutureWatcher
и это сигналы для уведомлений о готовности результата. Решения для уведомлений на чистом C ++ намного более сложные, и обратные вызовы также являются чем-то, что необходимо перетаскивать через иерархию классов. Очевидно, что каждый рабочий связывает поток с соединениями с БД.
Хорошо, все это можно написать, но ... пользовательский пул потоков будет означать отсутствие удобства QtConcurrent
, кажется, существуют только рискованные способы создания что QFuture
чтобы его мог вернуть таможенный работник. QThreadPool
бесполезен, потому что было бы целой большой историей создать постоянные исполняемые объекты в нем. Другими словами, шаблон, который я кратко описал, станет неким ядром проекта, который используется во многих местах, а не чем-то, что можно легко заменить на 100 ручных операций с нитями.
Короче говоря, если Я мог бы подсказать QFuture
за мои результаты, проблема будет решена. Может ли кто-нибудь указать мне на решение или обходной путь? Буду благодарен за любые яркие идеи.
UPD:
@ Владимир Бершов предложил хорошее современное решение, которое реализует паттерн наблюдателя. После некоторого поиска я нашел библиотеку QPromise . Конечно, создание пользовательского QFuture
все еще хакерское и может быть сделано только через недокументированный класс QFutureInterface
, но все же какое-то "обещающее" решение делает асинхронные вызовы более точными, насколько я могу судить.