Есть рабочий поток с вычислениями.
Есть модальное диалоговое окно для отображения прогресса.
Надо дать пользователю возможность прервать поток.
Как правильно это сделать?
Здравствуйте, nervous, Вы писали:
N>Hi all.
N>Есть рабочий поток с вычислениями. N>Есть модальное диалоговое окно для отображения прогресса. N>Надо дать пользователю возможность прервать поток. N>Как правильно это сделать?
Э-эх!.. Как оно там... Если вычисления в цикле (а так оно скорей всего и есть), то как-то так:
Здравствуйте, nervous, Вы писали:
N>Hi all.
N>Есть рабочий поток с вычислениями. N>Есть модальное диалоговое окно для отображения прогресса. N>Надо дать пользователю возможность прервать поток. N>Как правильно это сделать?
Можно, например, так:
#include <boost/thread/mutex.hpp>
#include <boost/thread.hpp>
void DoCalculations(int i);
void UpdateProgress(int i);
bool IsUserReadyToExit();
int const stepsNumber = 10;
boost::mutex monitor;
bool goingToExit = false;
void WorkThread()
{
for (int i = 0; i < stepsNumber; ++i)
{
DoCalculations(i);
{
boost::mutex::scoped_lock lk(monitor);
if (goingToExit)
return;
}
UpdateProgress(i);
}
}
int main()
{
boost::thread workThread(WorkThread);
while (!IsUserReadyToExit()) {}
{
boost::mutex::scoped_lock lk(monitor);
goingToExit = true;
}
workThread.join();
}
Здравствуйте, nervous, Вы писали:
N>Hi all.
N>Есть рабочий поток с вычислениями. N>Есть модальное диалоговое окно для отображения прогресса. N>Надо дать пользователю возможность прервать поток. N>Как правильно это сделать?
Здравствуйте, Azir, Вы писали:
A>Здравствуйте, nervous, Вы писали:
N>>Hi all.
N>>Есть рабочий поток с вычислениями. N>>Есть модальное диалоговое окно для отображения прогресса. N>>Надо дать пользователю возможность прервать поток. N>>Как правильно это сделать?
A>Можно, например, так:
A>
A>#include <boost/thread/mutex.hpp>
A>#include <boost/thread.hpp>
A>void DoCalculations(int i);
A>void UpdateProgress(int i);
A>bool IsUserReadyToExit();
A>int const stepsNumber = 10;
A>boost::mutex monitor;
A>bool goingToExit = false;
A>void WorkThread()
A>{
A> for (int i = 0; i < stepsNumber; ++i)
A> {
A> DoCalculations(i);
A> {
A> boost::mutex::scoped_lock lk(monitor);
A> if (goingToExit)
A> return;
A> }
A> UpdateProgress(i);
A> }
A>}
A>int main()
A>{
A> boost::thread workThread(WorkThread);
A> while (!IsUserReadyToExit()) {}
A> {
A> boost::mutex::scoped_lock lk(monitor);
A> goingToExit = true;
A> }
A> workThread.join();
A>}
A>
Я конечно не знаю как там в юниксах это делается, может и так, но в виндах это слишком расточительно, обертывать одну переменную мьютексом.
Не ужто нет переносимого решения для Intelocked функций?
Здравствуйте, Patalog, Вы писали:
P>Здравствуйте, Denwer, Вы писали:
P>хъ
D>>Я конечно не знаю как там в юниксах это делается, может и так, но в виндах это слишком расточительно, обертывать одну переменную мьютексом.
P>Для виндов mutex::scoped_lock==CRITICAL_SECTION
Это тоже расточительно по сравнения с интерлокед функциями.
Здравствуйте, Denwer, Вы писали:
D>Это тоже расточительно по сравнения с интерлокед функциями.
Не, не расточительно, в том случае, если переменную фактически использует только один поток и они не пытаются использовать ее одновременно. Тогда EnterCriticalSecton — просто десяток ассеблерных команд без всяких жутких усыплений.
Правильно работающая программа — просто частный случай Undefined Behavior
Здравствуйте, _Winnie, Вы писали:
_W>Здравствуйте, Denwer, Вы писали:
D>>Это тоже расточительно по сравнения с интерлокед функциями.
_W>Не, не расточительно, в том случае, если переменную фактически использует только один поток и они не пытаются использовать ее одновременно. Тогда EnterCriticalSecton — просто десяток ассеблерных команд без всяких жутких усыплений.
Круто круто, и зачем тогда вообще нужна критическая секция для одного потока.
Здравствуйте, Azir, Вы писали:
A>Можно, например, так:
A>[ccode] A>#include <boost/thread/mutex.hpp> A>#include <boost/thread.hpp>
A> DoCalculations(i); A> { A> boost::mutex::scoped_lock lk(monitor); A> if (goingToExit) A> return; A> } A> UpdateProgress(i); A> } A> boost::thread workThread(WorkThread); A> while (!IsUserReadyToExit()) {} A> { A> boost::mutex::scoped_lock lk(monitor); A> goingToExit = true;
Решил в отдельную тему вопрос не выводить (забьют минусами :) ). Смотрю на эту возню с бустом и не понимаю, зачем огород городить ? Почему не написать CreateThread(...., WorkThread, &dw) вместо boost::thread workThread(WorkThread) ? Чем лучше буст ? У меня одно объяснение: переносимость кода. Или я не прав ?
Цель деятельности всех программистов – чтобы их деятельность стала не нужна.
А что, собст. не так? Возврат значения InterlockedExchange нихрена не атомарно, в отличии от собственно Exchange.
Подход с циклом много где применяется, напр. Handy Features in Windows, and Interlocked Functions
D>Неудосужилиись даже volatile поставить перед long l_;
Хм, может конечно и надо бы поставить, но ведь оно по значению не меняется, а только по указателю...
Здравствуйте, Patalog, Вы писали:
P>Здравствуйте, Denwer, Вы писали:
P>хъ
D>>Это тоже не то. Это реализация функционала мьютекса через интерлокед функции. Что совсем отличное от самих интерлокед функций.
P>А какое отношение это имеет к рассматриваемому вопросу?
К первому посту никакого отношения не имеет, а дольше было предложено решение
boost::mutex::scoped_lock lk(monitor);
if (goingToExit)
return;
Я и сказал что это очень не эффективно, даже если там будет критическая секция, для этого примера самое то использовать интерлокед функции.
D>>
D>>Этож надо было такое написать.
P>А что, собст. не так? Возврат значения InterlockedExchange нихрена не атомарно, в отличии от собственно Exchange. P>Подход с циклом много где применяется, напр. Handy Features in Windows, and Interlocked Functions
Это как так? Не понял?
Может они и применяются, но у это явно не лучшее решение для быстрого мьютекса.
D>>Неудосужилиись даже volatile поставить перед long l_;
P>Хм, может конечно и надо бы поставить, но ведь оно по значению не меняется, а только по указателю...
хъ
P>>А что, собст. не так? Возврат значения InterlockedExchange нихрена не атомарно, в отличии от собственно Exchange. P>>Подход с циклом много где применяется, напр. Handy Features in Windows, and Interlocked Functions
D>Это как так? Не понял?
Имелось в виду то, что в
long ret = InterlockedExchange(&target, 1);
InterlockedExchange может вернуть 1. А нам нужен именно 0, чтобы быть уверенным, что никто другой не владеет мьютексом.
D>Может они и применяются, но у это явно не лучшее решение для быстрого мьютекса.
Критикуя — предлагай! Как бы ты реализовал lightweight_mutex?
Здравствуйте, Patalog, Вы писали:
P>Здравствуйте, Denwer, Вы писали:
P>хъ
P>>>А что, собст. не так? Возврат значения InterlockedExchange нихрена не атомарно, в отличии от собственно Exchange. P>>>Подход с циклом много где применяется, напр. Handy Features in Windows, and Interlocked Functions
D>>Это как так? Не понял?
P>Имелось в виду то, что в P>
P>long ret = InterlockedExchange(&target, 1);
P>
P>InterlockedExchange может вернуть 1. А нам нужен именно 0, чтобы быть уверенным, что никто другой не владеет мьютексом.
Кстати именно об этой проблеме писал насколько я помню Рихтер где то.
D>>Может они и применяются, но у это явно не лучшее решение для быстрого мьютекса.
P> Критикуя — предлагай! Как бы ты реализовал lightweight_mutex?
Здравствуйте, nervous, Вы писали:
N>Hi all.
N>Есть рабочий поток с вычислениями. N>Есть модальное диалоговое окно для отображения прогресса. N>Надо дать пользователю возможность прервать поток. N>Как правильно это сделать?
Я смотрю тут у ребят мозги совсем затекли.
Вот самое простое, эффективное и верное решение.
KV>Решил в отдельную тему вопрос не выводить (забьют минусами ). Смотрю на эту возню с бустом и не понимаю, зачем огород городить ? Почему не написать CreateThread(...., WorkThread, &dw) вместо boost::thread workThread(WorkThread) ? Чем лучше буст ? У меня одно объяснение: переносимость кода. Или я не прав ?