Russian Qt Forum
Ноябрь 26, 2024, 22:41 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: 1 [2] 3   Вниз
  Печать  
Автор Тема: QProcess и QThread  (Прочитано 13568 раз)
Базиля
Гость
« Ответ #15 : Декабрь 03, 2013, 05:56 »

Хммм, интересно  Улыбающийся
А там простая программка, которой на вход подается число, а на выходе квадрат этого числа.
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #16 : Декабрь 04, 2013, 10:09 »

Я на OSX и воспользоваться 1.exe не смог, сделал такое консольное приложение
Код
C++ (Qt)
#include <stdio.h>
#include <stdlib.h>
 
int main( void )
{
char buf[512];
gets(buf);
int val = atoi(buf);
printf("%d", val * val);
return 0;
}
 
Ну отрабатывает все 1000 раз, ошибок нет. Немного покрутил Ваш исходник (на всякий случай прилагаю) - результат тот же, ошибок нет
Записан
CuteBunny
Гость
« Ответ #17 : Декабрь 04, 2013, 17:23 »

У меня 1.exe не запустился - это хорошо или плохо? Плачущий

Как его 1.exe использовать? Там число через argc, argv? А на чем написано?

Исходный код 1.exe в студию!
« Последнее редактирование: Декабрь 04, 2013, 17:31 от kvv » Записан
Базиля
Гость
« Ответ #18 : Декабрь 04, 2013, 23:20 »

Спасибо за ответы! Улыбающийся

Я на OSX и воспользоваться 1.exe не смог, сделал такое консольное приложение
Код
C++ (Qt)
#include <stdio.h>
#include <stdlib.h>
 
int main( void )
{
char buf[512];
gets(buf);
int val = atoi(buf);
printf("%d", val * val);
return 0;
}
 
Ну отрабатывает все 1000 раз, ошибок нет. Немного покрутил Ваш исходник (на всякий случай прилагаю) - результат тот же, ошибок нет
Благодарю!
Учту ваши изменения, все никак не могу избавиться от "магических чисел", пора лупить себя по рукам Улыбающийся

Что же тогда делать, ума не приложу.
Попробую тогда на другой ОС запустить (текущая XP), посмотрим что выйдет, глупо конечно на это надеяться, проблема явно в другом, но других идей нет Грустный

У меня 1.exe не запустился - это хорошо или плохо? Плачущий

Как его 1.exe использовать? Там число через argc, argv? А на чем написано?

Исходный код 1.exe в студию!
Странно, что не запускается.

Вот сам код
Код:
#include <iostream>

using namespace std;

int main() {
int n;
cin >> n;
cout << n * n;
return 0;
}
Записан
Old
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4350



Просмотр профиля
« Ответ #19 : Декабрь 05, 2013, 09:23 »

Что же тогда делать, ума не приложу.
Скажите, а у вас установлен антивирус?
Попробуйте его отключить на время теста.

А делать нужно будет следующее: правильно обрабатывать ошибки и перезапускать процессы завершившиеся с ошибкой.
Записан
Базиля
Гость
« Ответ #20 : Декабрь 06, 2013, 00:34 »

Скажите, а у вас установлен антивирус?
Попробуйте его отключить на время теста.

А делать нужно будет следующее: правильно обрабатывать ошибки и перезапускать процессы завершившиеся с ошибкой.

Насчет антивируса уже приходила мысль Улыбающийся
Отключал - бесполезно Грустный

Скорее всего так и придется поступать.
Записан
Базиля
Гость
« Ответ #21 : Декабрь 08, 2013, 14:46 »

Господа, проверил я это все дело на Ubuntu.
И как ни странно, но все прекрасно работает! Улыбающийся
Спасибо огромное всем отозвавшимся!

Теперь уже проблема ясна -  нюансы были в ОС , нет ни у кого случайно предположений на этот счет?
Хотелось бы просто дальше продолжать писать на родном XP  Смеющийся

Спасибо!
« Последнее редактирование: Декабрь 08, 2013, 14:49 от Базиля » Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #22 : Декабрь 08, 2013, 14:57 »

Теперь уже проблема ясна -  нюансы были в ОС , нет ни у кого случайно предположений на этот счет?
Так это нырять болото Вындоуз Улыбающийся Для начала перебрать 1.exe c multi-threaded (DLL), да и с Debug и без - там это запросто может быть по-разному. 
Записан
Базиля
Гость
« Ответ #23 : Декабрь 08, 2013, 16:22 »

Для начала перебрать 1.exe c multi-threaded (DLL), да и с Debug и без - там это запросто может быть по-разному.
Думаете что проблема все-таки в exe файле?
Записан
ViTech
Гипер активный житель
*****
Offline Offline

Сообщений: 858



Просмотр профиля
« Ответ #24 : Декабрь 09, 2013, 13:23 »

У меня 1.exe не запустился - это хорошо или плохо? Плачущий

Как его 1.exe использовать? Там число через argc, argv? А на чем написано?

Исходный код 1.exe в студию!
Странно, что не запускается.

Не странно. libgcc_s_dw2-1.dll и libstdc++-6.dll не в каждой винде есть Улыбающийся. Если хотите, чтоб тестировали именно этот 1.exe, соберите его со стандартными виндовыми библиотеками.

Попробуйте поставить задержку после запуска процесса, например:
Код:
    process.start( fileExe );
    Sleep(100); // 200 или еще сколько, чтобы процесс успел запуститься
потому что в
Код:
    if ( !process.waitForStarted() ) {
насколько я разобрался, фактического ожидания не происходит. Метод возвращает true сразу после CreateProcess(...). Хотя это еще от версии Qt зависит. В 4.8 еще дают 20 мсек на размышления Улыбающийся, а в 5.1 выходят сразу. Подробности в <Qt>\src\corelib\io\qprocess_win.cpp.
« Последнее редактирование: Декабрь 09, 2013, 13:33 от ViTech » Записан

Пока сам не сделаешь...
Базиля
Гость
« Ответ #25 : Декабрь 10, 2013, 23:06 »


Не странно. libgcc_s_dw2-1.dll и libstdc++-6.dll не в каждой винде есть Улыбающийся. Если хотите, чтоб тестировали именно этот 1.exe, соберите его со стандартными виндовыми библиотеками.
Не подумал Улыбающийся
Попробуйте поставить задержку после запуска процесса, например:
Код:
    process.start( fileExe );
    Sleep(100); // 200 или еще сколько, чтобы процесс успел запуститься
потому что в
Код:
    if ( !process.waitForStarted() ) {
насколько я разобрался, фактического ожидания не происходит. Метод возвращает true сразу после CreateProcess(...). Хотя это еще от версии Qt зависит. В 4.8 еще дают 20 мсек на размышления Улыбающийся, а в 5.1 выходят сразу. Подробности в <Qt>\src\corelib\io\qprocess_win.cpp.
Но документация говорит об обратном:
Цитировать
bool QProcess::waitForStarted(int msecs = 30000)
Blocks until the process has started and the started() signal has been emitted, or until msecs milliseconds have passed.

Returns true if the process was started successfully; otherwise returns false (if the operation timed out or if an error occurred).
Непонимающий

Я в тестах отслеживал статус процесса - ни разу не было такой ситуации, чтобы я начинал запись в не запущенный процесс.
P.S. Ради интереса решил попробовать - ничего не изменилось(

В общем к чему я пришел.
Если убрать строчку кода:
Код:
if ( !process.waitForBytesWritten( time ) ) {
    //бла-бла-бла
}
То все работает как часы - я записываю данные, а потом читаю.
Ошибок пока что нет.

Но стоит оставить этот if, как на каком-нибудь из процессов функция обязательно вернет false.
В документации говорится, что это возможно только в 2-ух случаях:
Цитировать
Returns true if a payload of data was written to the device; otherwise returns false (i.e. if the operation timed out, or if an error occurred).
Тайм аут - исключено.
Насчет ошибки - тоже. Ибо функция process.errorString() возвращает unknwon error.
А сигнал error даже не испускается.

Единственное, что я обнаружил - в тех случаях когда эта функция возвращает false, перед проверкой этого условия, процесс закрылся, т.е. его статус с 2 сменился на 0:
Цитировать
0 - The process is not running.
1 - The process is starting, but the program has not yet been invoked.
2 - The process is running and is ready for reading and writing.
Почему это так происходит, не понятно.
По логике вещей - убрав эту злосчастную проверку, ситуация должна была бы повториться - на проверке следующего условия
Код:
 if ( !process.waitForReadyRead( time ) ) {
    //бла-бла-бла
}
Но такого не происходит Грустный
« Последнее редактирование: Декабрь 10, 2013, 23:24 от Базиля » Записан
Базиля
Гость
« Ответ #26 : Декабрь 11, 2013, 00:25 »

Прошу прощения, я кажется разобрался с проблемой  Смеющийся Смеющийся Смеющийся
Я просто немного идиот  Улыбающийся

Для тестирования выбрал не совсем удачный процесс.
После ввода информации в процесс, он успевал сразу завершаться, прежде чем я попытаюсь проверить - удачно ли записалась в него информация или готов ли вообще процесс к считывания с него байтов.
Функция естественно возвращал false - т.к. на момент проверки процесс уже был завершен.
Просто мне везло в ряде тестов и процесс успевал не завершаться до проверки этих условий.
Это меня и вводило в заблуждение.
Я уже просто голову себе сломал, начал рыть не в том месте яму, а проблема оказалась совершенно в другом Улыбающийся

Как я понял здесь только один вариант - добавить дополнительное условие на текущую активность процесса. Я прав?

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

Я подозреваю, что лучше тогда просто ловить сигнал readyRead.
« Последнее редактирование: Декабрь 11, 2013, 00:37 от Базиля » Записан
Majestio
Гость
« Ответ #27 : Декабрь 11, 2013, 08:52 »

P.S. И сразу такой вопрос назрел - если процесс завершился, а я программно не успел считать с него данные, они пропадут?

Попробуйте запускать процесс немного по другому.
Вот пример, где слот запускает внешний процесс, записывает данные в STDIN этого процесса, ожидает завершения, читает STDOUT процесса:

Код:
void MainWindow::SlotRun()
{
    QProcess *P = new QProcess();
    qDebug() << "Start";
    P->setReadChannelMode(QProcess::MergedChannels);
    P->start(tr("cmd.exe"),QStringList() << tr("/c") << QCoreApplication::applicationDirPath()+"/StartHidden.cmd" << tr("Argument"));
    QString strings("String4\nString2\nString3\nString1");
    P->write(strings.toLocal8Bit());
    P->closeWriteChannel();
    P->waitForFinished();
    QTextCodec *Cp866 = QTextCodec::codecForName("IBM 866");
    qDebug() << Cp866->toUnicode(P->readAllStandardOutput());
    qDebug() << "Stop";
    delete P;
}

Сделал "процесс" отрабатывающим достаточно быстро:

StartHidden.cmd
Код:
sort
echo Result: %1

Код:
« Последнее редактирование: Декабрь 11, 2013, 08:55 от Majestio » Записан
ViTech
Гипер активный житель
*****
Offline Offline

Сообщений: 858



Просмотр профиля
« Ответ #28 : Декабрь 11, 2013, 12:03 »

Но документация говорит об обратном:
Цитировать
bool QProcess::waitForStarted(int msecs = 30000)
Blocks until the process has started and the started() signal has been emitted, or until msecs milliseconds have passed.

Returns true if the process was started successfully; otherwise returns false (if the operation timed out or if an error occurred).
Непонимающий

Я в тестах отслеживал статус процесса - ни разу не было такой ситуации, чтобы я начинал запись в не запущенный процесс.
В документации написано, как метод должен работать в общем случае, на всех платформах, при удачном расположении планет Улыбающийся. Но истина всегда в исходниках. В частности, для виндовс можно увидеть следующее:
Код
C++ (Qt)
...
   success = CreateProcess(0, (wchar_t*)args.utf16(),
                           0, 0, TRUE, dwCreationFlags,
                           environment.isEmpty() ? 0 : envlist.data(),
                           workingDirectory.isEmpty() ? 0 : (wchar_t*)QDir::toNativeSeparators(workingDirectory).utf16(),
                           &startupInfo, pid);
   if (!success) {
       // Capture the error string before we do CloseHandle below
       q->setErrorString(QProcess::tr("Process failed to start: %1").arg(qt_error_string()));
   }
 
   if (stdinChannel.pipe[0] != INVALID_Q_PIPE) {
       CloseHandle(stdinChannel.pipe[0]);
       stdinChannel.pipe[0] = INVALID_Q_PIPE;
   }
   if (stdoutChannel.pipe[1] != INVALID_Q_PIPE) {
       CloseHandle(stdoutChannel.pipe[1]);
       stdoutChannel.pipe[1] = INVALID_Q_PIPE;
   }
   if (stderrChannel.pipe[1] != INVALID_Q_PIPE) {
       CloseHandle(stderrChannel.pipe[1]);
       stderrChannel.pipe[1] = INVALID_Q_PIPE;
   }
 
   if (!success) {
       cleanup();
       processError = QProcess::FailedToStart;
       emit q->error(processError);
       q->setProcessState(QProcess::NotRunning);
       return;
   }
 
   q->setProcessState(QProcess::Running);
...
Между функцией CreateProcess и установкой статуса процесса в QProcess::Running нет никаких ожиданий. В конце метода только строка
Код
C++ (Qt)
   // give the process a chance to start ...
   Sleep(SLEEPMIN * 2);
в версии 4.8, которую в 5-ой уже убрали. Это метод QProcessPrivate::startProcess() в <Qt>\src\corelib\io\qprocess_win.cpp. В этом файле можно посмотреть всю работу с процессами в винде. Для линукса поведение отличается, и там, на сколько я понял, есть какое-то ожидание(подтверждение) при запуске процесса.

К тому же, какой момент времени считать, что процесс "запустился"?
1. Завершилась системная функция запуска процесса.
2. Создались и готовы к работе каналы ввода/вывода.
3. Запустился главный(первый) поток процесса.
4. Создался и проинициализировался основной объект процесса.
5. Создалось главное окно приложения.
6. Главное окно отобразилось на экране.
7. ...

Какого момента в программе надо дождаться, чтобы считать процесс запущенным? И кто такой момент сможет сообщить? Улыбающийся Так что нет никакой магии, и статус QProcess::Running еще ничего не гарантирует.

Работа с каналами ввода/вывода тоже может не одинаково выполняться в разных ОС. Тут только плотное тестирование поможет Улыбающийся.
Записан

Пока сам не сделаешь...
Базиля
Гость
« Ответ #29 : Декабрь 19, 2013, 17:12 »

Извините, что пропал.

ViTech
Majestio
Спасибо Вам за информацию!

ViTech
Если я  все правильно понял, возможна ли такая ситуация, когда я могу попытаться записать какую-то информацию в еще не запущенный процесс?
Как тогда лучше всего определять время ожидания для запуска процесса?
Ведь сейчас нам может понадобиться около 200 мс, а при следующем запуске, к примеру, все 300 мс.

И как тогда в таком случае сам QProcess поймет, что процесс еще не запущен, если статус не гарантирует текущее состояние процесса?
Записан
Страниц: 1 [2] 3   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.132 секунд. Запросов: 23.