Как иметь один экземпляр QNetworkAccessManager? - PullRequest
0 голосов
/ 05 июня 2018

Есть похожий вопрос , но я не нашел его полезным для моей проблемы.

В документации Qt они говорят:

Одного экземпляра QNetworkAccessManager должно быть достаточно для всего приложения Qt.

В моем приложении я использовал QNetworkAccessManager в нескольких местах (их можно вызывать одновременно), и каждый раз, когда я создавал новый экземпляр в стеке.После прочтения этой цитаты я изменил свой код на статический QNetworkAccessManager и использовал его везде.После изменения статического члена я всегда получаю предупреждение:

QObject::connect: Cannot connect (null)::aboutToQuit() to QNativeWifiEngine::closeHandle()

В обоих случаях код работает без ошибок, однако эта документация меня немного смущает.Поскольку продукт будет коммерческим, я отношусь к этому вопросу серьезно.Должен ли я следовать документации или избежать предупреждения?Или вы предлагаете какие-либо другие способы?

Что если объекту в другом потоке необходимо использовать QNetworkAccessManager?


РЕДАКТИРОВАТЬ: добавление кода

SingletonКласс настроек:

class ConnectionSettingsSingleton
{
   ...
   // constructors = default
   // copy constructor = delete

   public:
      static QNetworkAccessManager networkAccessManager;
}

Я использую networkAccessManager в разных местах, но одинаково:

QNetworkReply* HttpClient::makeRequest()
{
   switch (this->method) {
   case RequestMethod::GET:
      return ConnectionSettingsSingleton::networkAccessManager.get(this->serverRequest);
   case RequestMethod::POST:
      return ConnectionSettingsSingleton::networkAccessManager.post(this->serverRequest, QJsonDocument(this->data).toJson());
   case RequestMethod::DELETE:
      return ConnectionSettingsSingleton::networkAccessManager.deleteResource(this->serverRequest);
   default:
      return nullptr;
   }
}


РЕДАКТИРОВАТЬ-2

Я был любезениспользуя ответ Кубы Обера и в какой-то момент я получил это предупреждение:

QObject: Cannot create children for a parent that is in a different thread.
(Parent is QNetworkAccessManager(0x26f6d0), parent's thread is QThread(0x2b73b8), current thread is QThread(0xa4f20a8)

Причина: я попытался получить доступ к QNAM из другого потока.Соответственно я обновил свой вопрос.

1 Ответ

0 голосов
/ 05 июня 2018

В вашем распоряжении весь Qt.Не используйте для этого статические переменные - вы не управляете их временем жизни, и это время жизни почти всегда неверно.QNetworkManager не должно существовать, когда QCoreApplication не существует.Предупреждение не является доброкачественным - оно указывает на фундаментальную проблему дизайна. Вы должны контролировать время жизни менеджера и следить за тем, чтобы он не пережил QApplication.Канонический способ управления такими глобальными объектно-связанными объектами - сохранять их как автоматические переменные в main и использовать вспомогательные функции для доступа к ним.QPointer автоматически отслеживает время жизни объекта и, таким образом, никогда не будет зависать.Таким образом:

main.h - интерфейс

QNetworkAccessManager *nMgr();

main.cpp - реализация

// This pointer is local to the translation unit, and is an
// implementation detail. It's not used anywhere else.
static QPointer<QNetworkAccessManager> globalManager;

// The global accessor method
QNetworkAccessManager *nMgr() {
  Q_ASSERT(!qApp || QThread::currentThread() == qApp->thread());
  return globalManager;
}

int main(int argc, char *argv[]) {
  QApplication app(argc, argv);
  QNetworkAccessManager mgr;
  globalManager = &mgr;
  ...
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...