Russian Qt Forum

Qt => Общие вопросы => Тема начата: spectre71 от Июля 07, 2009, 10:09



Название: Как "усыпить" текущий поток?
Отправлено: spectre71 от Июля 07, 2009, 10:09
QThread::sleep(unsigned long);
QThread::msleep(unsigned long);
QThread::usleep(unsigned long);

Все эти методы protected ! Непонятно нафига и что с этим делать.

Решение из FAQ не приемлемо!



Название: Re: Как "усыпить" текущий поток?
Отправлено: p222 от Июля 07, 2009, 10:14
Код
C++ (Qt)
class Helper: public QThread {
public:
   static void msleep(int ms)
   {
       QThread::msleep(ms);
   }
};
.....
Helper::msleep(5);

Сам нашел вчера в интернете :-)


Название: Re: Как "усыпить" текущий поток?
Отправлено: pastor от Июля 07, 2009, 10:19
Решение из FAQ не приемлемо!

Чем?


Название: Re: Как "усыпить" текущий поток?
Отправлено: spectre71 от Июля 07, 2009, 10:40
Решение из FAQ не приемлемо!

Чем?

#ifdef Q_WS_WIN
   Sleep( milliseconds );
#endif

Хотя бы тем, что вызов Sleep() под Q_WS_WIN требует подключения "Windows.h".



Название: Re: Как "усыпить" текущий поток?
Отправлено: spectre71 от Июля 07, 2009, 11:01
Сам нашел вчера в интернете :-)

Спасибо, работает.

Но вопрос еще открыт, почему эти методы сделаны "protected" ?


Название: Re: Как "усыпить" текущий поток?
Отправлено: Авварон от Июля 07, 2009, 11:29
видимо вне контекста QThread они могут некорректно работать...


Название: Re: Как "усыпить" текущий поток?
Отправлено: spectre71 от Июля 07, 2009, 11:54
видимо вне контекста QThread они могут некорректно работать...

Не похоже. Код для Windows

Код
C++ (Qt)
void QThread::sleep(unsigned long secs)
{
   ::Sleep(secs * 1000);
}
 
void QThread::msleep(unsigned long msecs)
{
   ::Sleep(msecs);
}
 
void QThread::usleep(unsigned long usecs)
{
   ::Sleep((usecs / 1000) + 1);
}

Кто-нибудь может написать троллям, чтобы перенесли методы в public?


Название: Re: Как "усыпить" текущий поток?
Отправлено: Авварон от Июля 07, 2009, 12:08
для юникс там небось sleep, тоже багов с ним нету, да, надо бы попросить...


Название: Re: Как "усыпить" текущий поток?
Отправлено: BRE от Июля 07, 2009, 13:57
Системный вызов sleep усыпляет ту нить, в контексте которой делается вызов.
Предполагается, что вызывать QThread::sleep будут из метода QThread::run(), а из него данные методы будут доступны (т.к. protected).


Название: Re: Как "усыпить" текущий поток?
Отправлено: Авварон от Июля 07, 2009, 14:08
ну так мы и пытаемся усыпить контекст ТЕКУЩЕЙ нити (main)


Название: Re: Как "усыпить" текущий поток?
Отправлено: BRE от Июля 07, 2009, 14:34
ну так мы и пытаемся усыпить контекст ТЕКУЩЕЙ нити (main)
Тогда решение предложенное р222 будет нормально работать на всех поддерживаемых платформах.   :)
Просто усыпление главной нити не самое типичное действо.  ;)


Название: Re: Как "усыпить" текущий поток?
Отправлено: ритт от Июля 07, 2009, 18:10
а, собсна, зачем блокировать главный поток?


Название: Re: Как "усыпить" текущий поток?
Отправлено: spectre71 от Июля 08, 2009, 08:43
а, собсна, зачем блокировать главный поток?
Усыплять, а  не блокировать. Ситуаций может быть много, в основном их можно обойти, но часто проще сделать через sleep.
У меня, например, в двух случаях
1) Короткие 50 - 200 msecs, при выводе информации в splash-окно во время загрузки приложения, чтобы не было мелькания.
2) При доступе к ресурсу, например открытие файла. При интенсивной работе с файловой системой (под Windows), попытка открыть файл может провалиться и требуются несколько попыток с нарастающей задержкой.

Еще возможно для счетной задачи(программы), по циклу(длительному, но с быстро исполняемой итерацией), если хочется чтобы не была 100% загрузка CPU.


Название: Re: Как "усыпить" текущий поток?
Отправлено: ритт от Июля 08, 2009, 09:10
а, собсна, зачем блокировать главный поток?
Усыплять, а  не блокировать.
а усыпление поток не заблокирует, ага?

sleep в основном потоке может быть полезен *исключительно* в однопоточном приложении; для всех остальных случаев есть таймер и система событий.


Название: Re: Как "усыпить" текущий поток?
Отправлено: BRE от Июля 08, 2009, 09:37
sleep в основном потоке может быть полезен *исключительно* в однопоточном приложении; для всех остальных случаев есть таймер и система событий.
Я тоже пока придумал только одно применение - приложение является демоном. В остальных случаях тормозить основной поток как-то странно.


Название: Re: Как "усыпить" текущий поток?
Отправлено: spectre71 от Июля 08, 2009, 09:46
а усыпление поток не заблокирует, ага?
Это семантика.
Блокировка и усыпление неравнозначны, поэтому лучше использовать правильный термин.
Блокировка не всегда усыпляет поток!!! И блокировка имеет смысл при многопоточности.

sleep в основном потоке может быть полезен *исключительно* в однопоточном приложении; для всех остальных случаев есть таймер и система событий.
Не согласен.
Во-первых может сделано быть проще без таймера, как в (1) примере.
Во-вторых есть большая разница между отработкой по таймеру и через sleep. В первом случаее мы входим в цикл обработки сообщений, во втором нет. Собственно (2) пример на этом основан, блокирую интерфейс(в некоторых критических ситуациях) до того как получу(или не получу) доступ к ресурсу.




Название: Re: Как "усыпить" текущий поток?
Отправлено: denka от Июля 08, 2009, 09:53
А помоему проще да и правильней было бы вызывать processEvents для блокировки интерфейса


Название: Re: Как "усыпить" текущий поток?
Отправлено: spectre71 от Июля 08, 2009, 10:00
А помоему проще да и правильней было бы вызывать processEvents для блокировки интерфейса
Наоборот, вызывать processEvents если не хочешь блокировать интерфейс или определенные события!


Название: Re: Как "усыпить" текущий поток?
Отправлено: ритт от Июля 08, 2009, 10:08
первый пример, пришедший в голову - даблклик, посреди которого вклинивается sleep :)

блокировать поток дабы мессаги "не мелькали" ))
даже спорить лениво
не согласен - и не надо :)


Название: Re: Как "усыпить" текущий поток?
Отправлено: denka от Июля 08, 2009, 10:11
А помоему проще да и правильней было бы вызывать processEvents для блокировки интерфейса
Наоборот, вызывать processEvents если не хочешь блокировать интерфейс или определенные события!
Особенно он не блокируются с флагом QEventLoop::ExcludeUserInputEvents


Название: Re: Как "усыпить" текущий поток?
Отправлено: spectre71 от Июля 08, 2009, 10:35
блокировать поток дабы мессаги "не мелькали" ))
даже спорить лениво
не согласен - и не надо :)
Да и не надо спорить, можешь предложить простой вариант для следующей задачи:
 - Длительная загрузка данных с индикацией процесса загрузки
 - Каждый этап отображается в splash окне типа "Qt::ToolTip"
 - Должны быть отображены все сообщения, ни одно не должно быть потеряно! При этом чтобы для коротких этапов сообщения не
мелькали, а оставались не менее, допустим 200 ms
 - Индикацией процесса загрузки должна пропасть в момент окончания загрузки.
Пример:

Код
C++ (Qt)
void load (void) {
 SpalashInfo->show();
 SpalashInfo->info("Start Loading"); //200ms
 SpalashInfo->info("do1");  //1000ms
 do1() // 1000ms
 SpalashInfo->info("do2"); //200ms
 do2() // 10ms
 SpalashInfo->info("do3"); //200ms
 do3() // 50ms
 SpalashInfo->info("do4"); //500ms
 do4() // 500ms
 ...
 SpalashInfo->info("done"); // 200ms
 SpalashInfo->hide();
}
 








 


Название: Re: Как "усыпить" текущий поток?
Отправлено: spectre71 от Июля 08, 2009, 10:39
Особенно он не блокируются с флагом QEventLoop::ExcludeUserInputEvents
если не хочешь блокировать интерфейс или определенные события!
через processEvents ты не блокируешь, а наоборот.


Название: Re: Как "усыпить" текущий поток?
Отправлено: ритт от Июля 08, 2009, 10:45
могу, конечно ))
если это *важные* мессаги, выбрать для их отображения более потребное место, чем сплэш; если это мега-важные мессаги, показывать их через очередь QMessageBox'ов; если это мессаги не более важные, чем "запускается это", "читается то", показывать их на сплэше без всяких велосипедов.


Название: Re: Как "усыпить" текущий поток?
Отправлено: pastor от Июля 08, 2009, 10:46
> Длительная загрузка данных с индикацией процесса загрузки

Длительную загрузка данных можно (нужно) вынести в отдельный поток. Тогда не прийдется "трогать" гуевый поток


Название: Re: Как "усыпить" текущий поток?
Отправлено: BRE от Июля 08, 2009, 10:47
- Должны быть отображены все сообщения, ни одно не должно быть потеряно! При этом чтобы для коротких этапов сообщения не
мелькали, а оставались не менее, допустим 200 ms
Вот лично я, как пользователь, был бы против затормаживания программы ради возможности прочесть сообщение. Да и сообщения я буду читать максимум один раз (во время первого запуска), потом в это время буду заниматься более интересными делами.


Название: Re: Как "усыпить" текущий поток?
Отправлено: pastor от Июля 08, 2009, 10:48
если это *важные* мессаги, выбрать для их отображения более потребное место, чем сплэш; если это мега-важные мессаги, показывать их через очередь QMessageBox'ов; если это мессаги не более важные, чем "запускается это", "читается то", показывать их на сплэше без всяких велосипедов.

+1


Название: Re: Как "усыпить" текущий поток?
Отправлено: spectre71 от Июля 08, 2009, 11:02
могу, конечно ))
если это *важные* мессаги, выбрать для их отображения более потребное место, чем сплэш; если это мега-важные мессаги, показывать их через очередь QMessageBox'ов; если это мессаги не более важные, чем "запускается это", "читается то", показывать их на сплэше без всяких велосипедов.
Это статус загрузки, а не Мессаги.
И задача именно в показе всех (определенных) этапов. И если что-то выводиться, оно должно оставаться на определенный(не меньше некоторого заданного) промежуток времени, иначе смотриться плохо когда сообщения мелькают.
Я привел простой вариант, который реализован у меня. Естественно что минимальный промежуток должен быть достаточн мал (~50-200ms).


Название: Re: Как "усыпить" текущий поток?
Отправлено: spectre71 от Июля 08, 2009, 11:04
Длительную загрузка данных можно (нужно) вынести в отдельный поток. Тогда не прийдется "трогать" гуевый поток
В моем случае это не простое решение! Потребуется сложная синхронизация!


Название: Re: Как "усыпить" текущий поток?
Отправлено: pastor от Июля 08, 2009, 11:07
В моем случае это не простое решение! Потребуется сложная синхронизация!

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

Немного не пойму вот этого:

Цитировать
И если что-то выводиться, оно должно оставаться на определенный(не меньше некоторого заданного) промежуток времени, иначе смотриться плохо когда сообщения мелькают.

Если все дело в красоте, то это глупо тормозить процесс загрузки при больших объемах данных. Пусть будет 100 мелких сообщений умножаем на 200мс и уже получаем 20 сек выкинутые в воздух. Кому это нужно?


Название: Re: Как "усыпить" текущий поток?
Отправлено: spectre71 от Июля 08, 2009, 11:11
Вот лично я, как пользователь, был бы против затормаживания программы ради возможности прочесть сообщение. Да и сообщения я буду читать максимум один раз (во время первого запуска), потом в это время буду заниматься более интересными делами.
Это статус загрузки, нужен для того чтобы во время длительных действий было понятно что приложение не висит, а что-то делает.
Или запустилось и загружает данные итд...
А дополнительное замараживание(при необходимости) между выводами разных сообщений в окне статуса достаточно маленькое, чтобы не была заметна заморозка, но при этом достаточное чтобы сообщения не мелькали(что может раздражать пользователя)


Название: Re: Как "усыпить" текущий поток?
Отправлено: spectre71 от Июля 08, 2009, 11:23
Синхронизация чего с чем? Пусть данные грузятся в отдельном потоке, и,  когда это нужно, он будет подавать статус сообщения в главный поток. Там ты их ловишь и показываешь где нужно.
Ты прав, но это для меня не простое решение. При загрузке приложения это еще можно более менее просто сделать, а во время загрузки данных при работе пользователя, большинство объектов(дозагружаемых, перезагружаемых...) находятся в главном потоке, и передача их в другой поток требует сложной синхронизации.

Немного не пойму вот этого:
Цитировать
И если что-то выводиться, оно должно оставаться на определенный(не меньше некоторого заданного) промежуток времени, иначе смотриться плохо когда сообщения мелькают.

Если все дело в красоте, то это глупо тормозить процесс загрузки при больших объемах данных. Пусть будет 100 мелких сообщений умножаем на 200мс и уже получаем 20 сек выкинутые в воздух. Кому это нужно?
Никто не говорит что нужно доходить до крайности.
У меня например - 5-100(в зависимоти от ситуации) сообщений во время загрузки, и при общем времени 3-100 сек, потери 0.5-10 сек(приблизительно)


Название: Re: Как "усыпить" текущий поток?
Отправлено: BRE от Июля 08, 2009, 11:28
У меня например - 5-100(в зависимоти от ситуации) сообщений во время загрузки, и при общем времени 3-100 сек, потери 0.5-10 сек(приблизительно)
Когда будет много срочной работы, попробуй раз в три минуты останавливаться и размеренно считать до 10.  ;)
Терять на каждой загрузке по 10 сек (в сложных ситуациях), это перебор. Тебе не кажется?
И это для того, чтобы вывести сообщение, которое все равно никто читать не будет...  ;)


Название: Re: Как "усыпить" текущий поток?
Отправлено: alex12 от Июля 08, 2009, 11:29
Как вариант:
Код
C++ (Qt)
void widget::slot1()
{
 SpalashInfo->show();
 SpalashInfo->info("Start Loading"); //200ms
 SpalashInfo->info("do1");  //1000ms
 QTimer::singleShot (  200, this, SLOT( slot2() ) );
}
 
void widget::slot2()
{
 SpalashInfo->show();
 SpalashInfo->info("do2");  //1000ms
 QTimer::singleShot (  200, this, SLOT( slot3() ) );
}
 
void widget::slot3()
{
 SpalashInfo->show();
 SpalashInfo->info("Start Loading"); //200ms
 SpalashInfo->info("do3");  //1000ms
 QTimer::singleShot (  200, this, SLOT( slot4() ) );
}
 

Еще моджно строить автомат на void QObject::timerEvent(QTimerEvent *event).

Хотя ИМЕННО в данной задаче мне кажется использование тупого sleep оправдано.


Название: Re: Как "усыпить" текущий поток?
Отправлено: spectre71 от Июля 08, 2009, 11:39
Как вариант:
...
Еще моджно строить автомат на void QObject::timerEvent(QTimerEvent *event).

Хотя ИМЕННО в данной задаче мне кажется использование тупого sleep оправдано.
Я могу делать SpalashInfo->show() , SpalashInfo->hide() совершенно в разных местах и не один раз.
Могу поменять мин интервал в любой момент SpalashInfo->minInfoInterval(int).
SpalashInfo сам определяет сколько нужно сделать доп. задержку(или не нужно), между показами сообщений.
И все это очень просто делается через sleep.

Пока более правильного и более-менее простого решения не нашел.


Название: Re: Как "усыпить" текущий поток?
Отправлено: ритт от Июля 08, 2009, 11:41
нужен вывод в виде консоли, а не в виде мигающей строки.
как текстэдит положить на сплэш разберёшься?


Название: Re: Как "усыпить" текущий поток?
Отправлено: spectre71 от Июля 08, 2009, 12:02
нужен вывод в виде консоли, а не в виде мигающей строки.
как текстэдит положить на сплэш разберёшься?
Согласен, хорошее решение, если хочется отказаться от задержек и приемлем вывод статуса в виде списка!
Хорошо смотриться во время загрузки приложения. Возможно на загрузку приложения так и сделаю.

Но есть операция, когда это на мой взгляд будет смотреться не красиво:
- сохранение всех открытых проектов(в моем приложении). Пользователь в любой момент выбрает "Savt All", и делается сохранение, а в SplashInfo показываются имена сохраняемых проектов, списком будет смотреться не очень(слишком информативно)


Название: Re: Как "усыпить" текущий поток?
Отправлено: ритт от Июля 08, 2009, 12:35
сплэш на сохранение файла - вот где слишком информативно :)


Название: Re: Как "усыпить" текущий поток?
Отправлено: spectre71 от Июля 08, 2009, 12:49
сплэш на сохранение файла - вот где слишком информативно :)

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


Название: Re: Как "усыпить" текущий поток?
Отправлено: ритт от Июля 08, 2009, 14:19
если операция может быть действительно длительной, а гуй блокируется на всё это время (+простои потока на засыпание), конечный пользователь или возненавидит тебя до кончиков волос, либо скурится в перерывах (эта...автосохранение не забудь реализовать :) )

уж лучше бы тогда очередь и прогрессбар...не отнимай у людей возможность работать с приложением, пока оно что-то там своё злобное молча делает :)


Название: Re: Как "усыпить" текущий поток?
Отправлено: spectre71 от Июля 08, 2009, 14:39
если операция может быть действительно длительной, а гуй блокируется на всё это время (+простои потока на засыпание), конечный пользователь или возненавидит тебя до кончиков волос, либо скурится в перерывах (эта...автосохранение не забудь реализовать :) )

уж лучше бы тогда очередь и прогрессбар...не отнимай у людей возможность работать с приложением, пока оно что-то там своё злобное молча делает :)

Собственно про это я написал выше, но реализовать это в ближайшем времени проблематично, много заморочек с синхронизацией!
Соответственно автосохранение до тех пор будет делать неразумно.
А средний простой на засыпание порядка 10-20% и не является существенным  по сравнению с операцией сохранения.


Название: Re: Как "усыпить" текущий поток?
Отправлено: pastor от Июля 08, 2009, 15:09
имхо, нужно изначально писать правильно. Будешь писать дальше, софтина разрастется, захочешь что-то изменить и все это закончится переписываним почти с 0.

Но это только имхо


Название: Re: Как "усыпить" текущий поток?
Отправлено: ритт от Июля 08, 2009, 15:20
поток, список, сигнал прогресса...
синхронизация нужна, только если список будет изменяться в процессе работы потока (можешь за основу взять qfileinfogatherer - там уже всё есть)


Название: Re: Как "усыпить" текущий поток?
Отправлено: spectre71 от Июля 08, 2009, 16:07
поток, список, сигнал прогресса...
синхронизация нужна, только если список будет изменяться в процессе работы потока (можешь за основу взять qfileinfogatherer - там уже всё есть)

У меня все гораздо сложнее, сохранение проекта это не запись файла подобного ini, это сериализация достаточно сложно устроенного множества объектов с иерархическими и ссылочными отношениями. Прямо во время записи допускается ограниченное изменение состояний некоторых объектов(для этого делается синхронизация) - часть объектов прямо во время записи может менять состояние в других потоках. И это работает.
Вынесение записи проекта в другой поток - позволить пользователю параллельно с  записию делать дополнительные изменения состояний записываемых объектов, что потребует дополнительной синхронизации и весьма не простой. Поэтому пока и блокирую GUI.


Название: Re: Как "усыпить" текущий поток?
Отправлено: ритт от Июля 09, 2009, 01:27
я не говорил про изменение записываемых объектов.
попросту говоря, имеем двадцать одновременно открытых проектов -> пока сохраняется один, девятнаяцать ещё/уже можно редактировать.

ладно, тема исчерпана.


Название: Re: Как "усыпить" текущий поток?
Отправлено: spectre71 от Июля 09, 2009, 07:52
я не говорил про изменение записываемых объектов.
попросту говоря, имеем двадцать одновременно открытых проектов -> пока сохраняется один, девятнаяцать ещё/уже можно редактировать.

ладно, тема исчерпана.
Я понял что ты про это не говорил.
Но с тем проектом который сохраняется проблема все равно остается:
- блокировать работу пользователя именно с ним пока он сохраняется(если проект очень большой(1000-10000 задач) то это могут быть ~ 5-20 сек)
- как-то информировать пользователя об этом, чтобы ему не казалось что это какой-то глюк или тормоза
Не говоря уж о том что это тоже не просто, как-то странно оно будет выглядеть для пользователя, то один не доступен, то другой, а может и тот с которым он сейчас работает.
Так что проблему лучше будет решить без дополнительных промежуточных вариантов. А текущий вариант вполне прилично и понятно смотриться, если будет время, сделаю флеш и покажу как это выглядит.
С сохранением в другом потоке я согласен, надо будет обязательно сделать, но пока еще много более приоритетных задач.




Название: Re: Как "усыпить" текущий поток?
Отправлено: ритт от Июля 09, 2009, 08:26
я бы советовал взять за пример сохранение в кореле - там объекты могут исчисляться далеко не десятками тысяч - вот тогда-то и начинаются настоящие тормоза при открытии/сохранении...так они просто блокируют текущий документ на редактирование, а в статусбаре (если не вру) появляется прогрессбар с именем файла а-ля "файл_такой-то.цдр 50%"
хоть камень и загружен в это время на 99%, всё-равно можно в это время что-то делать. а на многоядерных железках вообще никаких неудобств


Название: Re: Как "усыпить" текущий поток?
Отправлено: Winstrol от Июля 09, 2009, 08:40
А в чем проблема сделать отдельный поток? Одна строка

futureWatcher.setFuture(QtConcurrent::run(&serializer,&Serializer::start));

Плюс сигналы finished() подключить и сигналы сообщающие о прогрессе внутри процедуры сериализации.

А вот менять данные в одном потоке, а в другом сохранять плохо. Изменения могут проходить неатомарно и изменения могут быть считаны в промежуточном состоянии.


Название: Re: Как "усыпить" текущий поток?
Отправлено: spectre71 от Июля 09, 2009, 09:46
я бы советовал взять за пример сохранение в кореле - там объекты могут исчисляться далеко не десятками тысяч - вот тогда-то и начинаются настоящие тормоза при открытии/сохранении...так они просто блокируют текущий документ на редактирование, а в статусбаре (если не вру) появляется прогрессбар с именем файла а-ля "файл_такой-то.цдр 50%"
хоть камень и загружен в это время на 99%, всё-равно можно в это время что-то делать. а на многоядерных железках вообще никаких неудобств

Ну, у меня сейчас для тестирования открыто 28 проектов и 425791 объектов которые сериализуются и сохраняются(~50% объектов ), специально в дибаг версии вывожу кол-во объектов(наследуемых от моего сериализуемого класса RW) в статус баре. Так вот, сохранение всех проектов(~200000  объектов, 28 файлов)  занимает 3-4 сек, а поднятие 5-6 сек.
Задача сводить к созданию копии проекта(в памяти) и сохранении уже копии. Поскольку некоторые проекты могут быть большими, то в общем случае операция может быть длительной и подвесит пользотельский интерфейс. Для копирования в другом потоке необходимо будет вставить в массу мест критическую секцию(на момент копирования), да еще и так чтобы блокировать только необходимые операции, иначе получиться все тоже подвисание интерфейса. Короче без хорошего рефакторинга не обойтись.


Название: Re: Как "усыпить" текущий поток?
Отправлено: ритт от Июля 09, 2009, 10:05
что-т я последний мессаг не понял - из-за чего будет подвисание? если сохраняешь копию, то вообще всё замечательно - повесил часики, снял снапшот(ы) в гуёвом потоке, убрал часики и в новом потоке сохраняешь снап...интерфейс вообще можно блокировать только на время копирования объектов в памяти...


Название: Re: Как "усыпить" текущий поток?
Отправлено: ритт от Июля 09, 2009, 10:20
кстати, вот - http://doc.trolltech.com/qq/qq27-responsive-guis.html


Название: Re: Как "усыпить" текущий поток?
Отправлено: spectre71 от Июля 09, 2009, 11:56
что-т я последний мессаг не понял - из-за чего будет подвисание? если сохраняешь копию, то вообще всё замечательно - повесил часики, снял снапшот(ы) в гуёвом потоке, убрал часики и в новом потоке сохраняешь снап...интерфейс вообще можно блокировать только на время копирования объектов в памяти...
Собственно я имел ввиду под подвисанием "часики", если проект большой, то это могут быть секунды, а если очень очень, то и десятки секунд, что неприятно для пользователя.


Название: Re: Как "усыпить" текущий поток?
Отправлено: spectre71 от Июля 09, 2009, 12:02
Кстати, натолкнулся на ситуацию когда точно нужен "public : sleep"!
Создаю QThread, в run вызываю метод некоторого объекта, а в методе объекта требуется sleep!


Название: Re: Как "усыпить" текущий поток?
Отправлено: Winstrol от Июля 09, 2009, 12:32
Кстати, натолкнулся на ситуацию когда точно нужен "public : sleep"!
Создаю QThread, в run вызываю метод некоторого объекта, а в методе объекта требуется sleep!
Чем плох политкорректый код из ссылки Константина?


Код
C++ (Qt)
QEventLoop q;
QTimer tT;
 
tT.setSingleShot(true);
connect(&tT, SIGNAL(timeout()), &q, SLOT(quit()));
tT.start(5000); // 5s timeout
q.exec();
 


Название: Re: Как "усыпить" текущий поток?
Отправлено: spectre71 от Июля 09, 2009, 12:51
Кстати, натолкнулся на ситуацию когда точно нужен "public : sleep"!
Создаю QThread, в run вызываю метод некоторого объекта, а в методе объекта требуется sleep!
Чем плох политкорректый код из ссылки Константина?
...
...

А тем, что не имеет к этому отношения.


Название: Re: Как "усыпить" текущий поток?
Отправлено: spectre71 от Июля 09, 2009, 13:02
Если интересно, вот как выглядит сохранение сейчас.
Только у "gif" цвета срезаются.


Название: Re: Как "усыпить" текущий поток?
Отправлено: BRE от Июля 09, 2009, 13:56
Как предложение. IMHO, лучше пусть в сплэше быстро мелькают имена проектов, и сохранение происходит быстрее. А для информирования пользователя завести журнал действий (log), в котором и выводить подробную информацию:
Сохраняется проект "ААА" - Ок
Сохраняется проект "БББ" - Ок
....
В него можно записывать и другие действия с подробными комментариями. Разместить его в закладке после Debug, например.


Название: Re: Как "усыпить" текущий поток?
Отправлено: Winstrol от Июля 09, 2009, 14:12
Как предложение. IMHO, лучше пусть в сплэше быстро мелькают имена проектов, и сохранение происходит быстрее.
ИМХО обращения к GUI потоку из вычислительных потоков должны быть ассинхронными. А GUI пусть сам разбирается с помощью таймеров и событий, сколько что показывать. Но автор предпочитает идти своим путем и блокировать вычислительный поток.
Кстати, фиктивный QWaitCondition никто не отменял.


Название: Re: Как "усыпить" текущий поток?
Отправлено: BRE от Июля 09, 2009, 14:22
ИМХО обращения к GUI потоку из вычислительных потоков должны быть ассинхронными. А GUI пусть сам разбирается с помощью таймеров и событий, сколько что показывать. Но автор предпочитает идти своим путем и блокировать вычислительный поток.
Кстати, фиктивный QWaitCondition никто не отменял.
Мое мнение, не надо вообще ничего замедлять! Я об это уже несколько раз писал.
А где автор будет делать сохранение (в основном потоке или в специальном), это его дело.
Не нужно дополнительно тормозить работу пользователя, ради вывода каких-то незначительных и не нужных ему сообщений.


Название: Re: Как "усыпить" текущий поток?
Отправлено: Winstrol от Июля 09, 2009, 14:41
Мое мнение, не надо вообще ничего замедлять! Я об это уже несколько раз писал.
А где автор будет делать сохранение (в основном потоке или в специальном), это его дело.
Не нужно дополнительно тормозить работу пользователя, ради вывода каких-то незначительных и не нужных ему сообщений.
ИМХО это вопрос вкуса, как обрабатывать сигнал сохраняющего потока. Либо показать окно, либо записать сообщение в лог. В обоих случаях потоку, реализующему сохранение, ничего не нужно знать о конкретной выбранной стратегии взаимодействия с пользователем. Его забота сохранять и сигналы кидать о текущем прогрессе.


Название: Re: Как "усыпить" текущий поток?
Отправлено: BRE от Июля 09, 2009, 16:15
ИМХО это вопрос вкуса, как обрабатывать сигнал сохраняющего потока. Либо показать окно, либо записать сообщение в лог. В обоих случаях потоку, реализующему сохранение, ничего не нужно знать о конкретной выбранной стратегии взаимодействия с пользователем. Его забота сохранять и сигналы кидать о текущем прогрессе.
Какие потоки сохранения?  ;)
Разговор завязался о целесообразности усыпления программы, для того чтобы пользователь успел прочитать сообщение. Я пишу только о этом.  :)


Название: Re: Как "усыпить" текущий поток?
Отправлено: Winstrol от Июля 09, 2009, 17:23
Какие потоки сохранения?  ;)
Разговор завязался о целесообразности усыпления программы, для того чтобы пользователь успел прочитать сообщение. Я пишу только о этом.  :)
Дык, если  не делать отдельный поток для сохранения, а делать все в GUI а затем блокировать по sleep (а не QEventLoop см. выше), то юзер все равно ничего не увидит  ;)


Название: Re: Как "усыпить" текущий поток?
Отправлено: BRE от Июля 09, 2009, 17:48
Дык, если  не делать отдельный поток для сохранения, а делать все в GUI а затем блокировать по sleep (а не QEventLoop см. выше), то юзер все равно ничего не увидит  ;)
Я против торможения вообще (хоть через sleep, хоть через таймер).  ;D


Название: Re: Как "усыпить" текущий поток?
Отправлено: spectre71 от Июля 09, 2009, 18:47
Все пора закрывать тему. Вроде уже обсудили все что можно.
Кому интересно, пусть читает с начала.