QNetworkAccessManager из ThreadPool

Очень принципиальный вопрос. В документации упоминается, что все методы в QNetworkAccessManager являются реентерабельными. Если да, то допустимо ли выполнение метода get() в QRunnable без блокировок? Мой код будет выглядеть примерно так:

class MyClass: public QRunnable
{
    void run()
    {
        ...
        QNetworkAccessManager nam;
        QNetworkReply* reply =  name.get(request)    // No Read-write lock.
        ...
    }
};

person Vishnu Pedireddi    schedule 06.05.2011    source источник


Ответы (2)


Из документации Qt:

[...] класс называется реентерабельным, если его функции-члены могут [одновременно] безопасно вызываться из нескольких потоков, при условии, что каждый поток использует другой экземпляр класса.

Поскольку вы каждый раз используете другой экземпляр (тот, который вы создаете в стеке в run()), вы в безопасности.

person Marc Mutz - mmutz    schedule 06.05.2011
comment
Если бы у меня был экземпляр QNetworkAccessManager, совместно используемый разными потоками, был бы вызов get по-прежнему действительным из разных потоков?? то есть, если экземпляр QNetworkAccessManager передается в QRunnable во время его создания, а его метод get вызывается в run(), как я упоминал выше, будет ли это гарантировать отсутствие проблем ?? - person Vishnu Pedireddi; 07.05.2011
comment
@de costa: нет, это взорвется. Вам понадобится QMutex для сериализации доступа к нему, но: QNetworkAccessManager — это QObject, и поэтому его необходимо moveToThread()ed для безопасного вызова, даже с защитой мьютекса (обработчики событий могут вызываться на QObject в момент практически в любое время). Поскольку QRunnable выполняется в потоке, который вы не можете предсказать извне QThreadPool, а moveToThread() может только проталкивать объект, а не извлекать из другого потока, вы не можете использовать QObject, которые в QRunnables, которые не были созданы там (если вы не синхронизируете их внутренне, т.е. не сделаете их потокобезопасными). - person Marc Mutz - mmutz; 07.05.2011
comment
В этом случае, насколько дорого будет создать QNetworkAccessManager для каждого отдельного QRunnable внутри ThreadPool?? Считается ли это хорошей практикой?? Другой альтернативной, но потенциально неотлаживаемой реализацией является наличие QObject в моем QRunnable и реализация связи сигнала/слота с QNetworkAccessManager, экземпляр которого был создан в потоке, создавшем QTHreadPool. Какие-либо предложения ?? - person Vishnu Pedireddi; 07.05.2011
comment
@de costo: Это то, что вы уже делаете в ОП. Что касается стоимости: QNetworkAccessManager в основном является параметризуемой фабрикой (как в абстрактной фабрике). Если вам не нужна параметризуемость (например, вы не хотите расширять ее дополнительными поддерживаемыми протоколами), создание ее тут же должно иметь минимальные накладные расходы. Если вы не можете использовать его таким образом по той или иной причине, просто используйте его в основном потоке, что является немного более идиоматичным способом. QNetworkReply являются QIODevices и поддерживают асинхронную операцию, например. сигнал readyRead(), поэтому вам не нужны потоки (нагрузка связана с вводом-выводом). - person Marc Mutz - mmutz; 07.05.2011
comment
@Marc Mutz: если мы используем более одного QNetworkAccessManager, сложно установить параметры кеша и прокси для всех из них. - person philk; 23.10.2013

В качестве примечания к этому, если вы просто хотите, чтобы запрос GET был асинхронным, QNetworkAccessManager уже является асинхронным (так сказано в документах).

person Abhijith    schedule 07.05.2011