Тайм-аут чтения QFile

Моему приложению необходимо читать файлы из точки монтирования nfs. Я использую QFile::read(BUFFER_SIZE);, который работает так, как должен. Проблема в том, что когда nfs размонтируется (неоднородные проблемы с сетью), этот QFile::read() никогда не истечет время ожидания, что приведет к зависанию приложения. Пожалуйста, какие-нибудь разумные решения?

Спасибо.


person ramtheconqueror    schedule 31.07.2014    source источник
comment
неоднородные проблемы с сетью. Можете ли вы проверить сетевую ошибку?   -  person TheDarkKnight    schedule 31.07.2014
comment
У QFile::readData ( char * data, qint64 maxSize ) такое же поведение?   -  person Nejat    schedule 31.07.2014


Ответы (3)


Я думаю, это связано с тем, как работает NFS. Процесс застрял в системном вызове ОС, в непрерывном спящем режиме. Итак, я думаю, у вас есть два надежных варианта:

  • Переместить чтение файла в другой поток. Он и его цикл событий могут застрять, просто закодируйте свой основной поток так, чтобы это не имело значения для всего приложения. Есть несколько способов использовать для этого потоки, но если вы не читаете произвольное количество разных файлов одновременно, вероятно, лучше всего будет запустить выделенный поток для чтения одного файла, а затем позволить поток заканчивается, как только все будет прочитано. Для этого вы можете даже просто создать подкласс QThread и переопределить метод run() своим собственным циклом чтения (вы все еще можете генерировать сигналы для прогресса, если хотите, вы просто не можете получать их в очереди без цикла событий Qt).

  • Переместить чтение файла в другой процесс. Другими словами, напишите небольшую инструментальную программу или скрипт, который выполняет фактическое чтение и отправляет содержимое вашему основному процессу. Таким образом, вы сможете остановить процесс чтения, не убивая все приложение, если в этом возникнет необходимость. Опять же, вам нужно решить, хотите ли вы отдельный одноразовый процесс для каждого чтения (чтобы вы могли указать имя файла в качестве параметра командной строки, например), или если вы запускаете один дочерний процесс и реализуете связь с ним, чтобы вы могли запрашивать файлы (или части файлов). Qt QProcess также упрощает этот подход.

person hyde    schedule 01.08.2014
comment
Спасибо за ваше время. Мы (команда разработчиков) немного поболтали и также придумали второе решение. Назад к моему столу, ваш ответ был здесь. Удивительно. Принимая это как ответ. - person ramtheconqueror; 01.08.2014

Вы можете использовать QFile::bytesAvailable (), унаследованный от QIODevice, который возвращает количество байтов, доступных для чтения. Подождите в цикле while, пока байты не будут доступны или не пройдет несколько секунд:

QFile file("file.dat");
file.open(QIODevice::ReadOnly);

QElapsedTimer timer;
timer.start();

while(file.bytesAvailable()<BUFFER_SIZE || timer.nsecsElapsed()<3e9)
    qApp->processEvents();

QByteArray array
if(file.waitForReadyRead())
{
   array = file.read(BUFFER_SIZE);
}

Здесь он будет ждать 3 секунды, пока данные будут готовы. Прошедшее время измеряется QElapsedTimer. Если BUFFER_SIZE байт недоступны после тайм-аута, то он будет продолжаться без зависаний.

person Nejat    schedule 31.07.2014
comment
Какая версия Qt поддерживает это? Я не могу найти waitForReadyRead() в документации Qt 4.8. Спасибо за вашу помощь. - person ramtheconqueror; 01.08.2014
comment
Настоящая проблема - функция file.read(). Даже после того, как вы убедитесь, что bytesAvaiable() и waitForReadyRead() равны true, если сеть отключается во время read(), приложение все равно зависает. - person ramtheconqueror; 01.08.2014

Вы можете использовать сигнал QIODevice::readChannelFinished() и подключить его к слоту, закрывающему программу чтения файлов.

person ahmed    schedule 31.07.2014
comment
Цикл событий активируется до тех пор, пока не вернется read(), будет ли этот сигнал работать? - person ramtheconqueror; 31.07.2014