Поиск:

Ответ в темуСоздание новой темы Создание опроса
> зависает окно при обработке 
:(
    Опции темы
mrgloom
Дата 29.6.2012, 10:20 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 829
Регистрация: 8.6.2011

Репутация: нет
Всего: нет



есть окно, на нём кнопка, на кнопке обработчик, в обработчике некоторая полезная работа которая требует времени.
точнее там 2 кнопки старт и стоп, хотелось бы чтобы по кнопке стоп можно было остановить процесс, т.е. вообще его прервать(т.е. все данные чтобы остановились на предыдущем шаге) или же хотя бы дождаться завершения текущего шага зафиксировать переменные и остановится.

Код

void CControlDlg::OnStart()
{
    is_not_stop=true;
    //имитация деятельности
    //Sleep(6000); 
    for(int64 j=0;j<10;++j)
        for(int64 i=0;i<1000000;++i)
   {
      if(is_not_stop)
         {
            int64 f= (double)i*cos((double)i)*sin((double)i);
            updateinfo();
         }
      else
           break;
   }
}
void CControlDlg::OnStop()
{
is_not_stop=false;
}


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

Это сообщение отредактировал(а) mrgloom - 29.6.2012, 10:21
PM MAIL   Вверх
vol4ek
Дата 29.6.2012, 16:54 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


конь в пальто
**


Профиль
Группа: Участник
Сообщений: 304
Регистрация: 1.5.2011
Где: Минск

Репутация: -1
Всего: 0



Код


static UINT Function(LPVOID param)
{
    // Здесь Ваш код

    return 0;
}

void CControlDlg::OnStart()
{
    AfxBeginThread(Function,this,0,0,THREAD_PRIORITY_IDLE ); 
}



Почитайте про потоки. smile 
PM MAIL ICQ   Вверх
Earnest
Дата 2.7.2012, 08:56 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 5962
Регистрация: 17.6.2005
Где: Рязань

Репутация: 87
Всего: 183



Потоки, да, но тогда не получится
Цитата

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

т.к. поток прерывается в любой момент. Ну то есть можно, но с доп. геморроем.

В твоей ситуации лучше разбить задачу на шаги - она и так у тебя разбита, как я понимаю. Каждый шаг оформить как ф-ю какого-то класса, который будет хранить все состояние процесса (те самые переменные, которые ты хочешь зафиксировать), а дальше 2 варианта:
1) цикл, управляемый PickMessage-DispatchMessage с проверкой не пора ли остановиться после каждого шага. В принципе, здесь не обязательно выделять шаг в отдельную функцию, но сложнее добиться полной прозрачности цикла для действий пользователя
2) выполнять каждый шаг по какому-то сообщению, которое самому- же себе и посылать - асинхронно, конечно. Т.е. крутится обычный стандартный цикл обработки сообщений, который кнопки обрабатывает и т.д. Чтобы запустить рабочий процесс (по нажатию кнопки старт), посылаешь сообщение, по получении которого выполняешь один шаг и тут же посылаешь новое сообщение. По нажатию кнопки стоп просто ставим флаг bStop, например. А обработчик нашего шагового сообщения сначала проверяет флаг, а уже потом выполняет свою работу. Или не выполняет. Как-то так.


--------------------
...
PM   Вверх
mrgloom
Дата 2.7.2012, 11:39 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 829
Регистрация: 8.6.2011

Репутация: нет
Всего: нет



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

Код

BOOL CControlDlg::PumpMessage(void)
{
   CWinThread *pThread = AfxGetThread();
   MSG msg;
   while(::PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE))
   {
       if (!pThread->PumpMessage()) 
           break; 
   }
   if(m_Session.State == PAUSED)
     return FALSE;
   return TRUE;
};



                    
Код

Sleep(6000); // имитация захвата кадра, трубется некоторое время
                    //for(int64 j=0;j<10;++j)
                    //for(int64 i=0;i<1000000;++i)
                    //{
                    //    if(PumpMessage()==TRUE)
                    //        int64 f= (double)i*cos((double)i)*sin((double)i);
                    //    else
                    //    {
                    //        //записываем тут текущее положение и выходим
                    //        return;
                    //    }
                    //}    

                    if(PumpMessage()==TRUE)
                    {
                    }
                    else
                    {
                        //записываем тут текущее положение и выходим
                        return;
                    }


так вот с такими единичными действиями тоже работает, но надо жать всё время на кнопку, у пользователя такое ощущение, что она зависла.
треды наверно не желательны т.к. там питон вызывается, а из треда он может закапризничать. 

Это сообщение отредактировал(а) mrgloom - 2.7.2012, 12:21
PM MAIL   Вверх
mrgloom
Дата 2.7.2012, 13:10 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 829
Регистрация: 8.6.2011

Репутация: нет
Всего: нет



решил вроде проблему так,

Код

UINT CControlDlg::thread_func(LPVOID param)
{
    INFO*  pSession= (INFO*)param;
    for(int r=0;r<pSession->NumRows;++r)
    {
        for(int c=0;c<pSession->NumCols;++c)
        {
            if(pSession->State == PAUSED)
            {
                //должны записать текущую позицию
                return 0;
            }
            Sleep(6000);
        }
    }
    return 0;
};


Код

void CControlDlg::OnStart()
{
CWinThread* myWinThread= AfxBeginThread(CControlDlg::thread_func,(LPVOID)&m_Session);
}


но проблема в том что когда нажимаешь стоп на форме, то состояние на форме сразу меняется, и не ждет окончания треда, а надо бы всё заморозить и дождаться окончания треда.
или надо в на кнопку стоп повесить еще WaitForSingleObject ?

Добавлено @ 13:16
но тогда непонятно почему строчка WaitForSingleObject выполняется и проходит сквозь неё, а только после этого выполняется возврат из треда?  т.е. мне нужно чтобы мы подождали пока тред закончит итерацию и  не делали до этого UpdateControl.

Код

void CControlDlg::OnPauseScan()
{

        m_Session.State = PAUSED;

        WaitForSingleObject(myWinThread,MAX_TIME_TO_WAIT_THREAD); //почему не ждем?

        UpdateControls();
}


Это сообщение отредактировал(а) mrgloom - 2.7.2012, 13:17
PM MAIL   Вверх
mrgloom
Дата 2.7.2012, 15:24 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 829
Регистрация: 8.6.2011

Репутация: нет
Всего: нет



ну вообщем вопрос я решил путем добавления глобальной булевой переменной, и тред когда завершается проставляем этот флаг.
а на обработчике кнопки стоп я добавил 
Цитата

while(!m_is_thread_finish)
  {
    Sleep(100);
  }

и теперь при нажатии на кнопку стоп, всё зависает на нажатом её состоянии и ждет пока тред закончит.
вообщем может и не самое лучшее решение, но я не знаю как по другому, теоретически можно менять статус на форме делать её не активной и выводить песочные часы.
PM MAIL   Вверх
mrgloom
Дата 5.7.2012, 16:41 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 829
Регистрация: 8.6.2011

Репутация: нет
Всего: нет



не могу понять как работает WaitForSingleObject.

Код

void CControlDlg::OnStart()
{
    //m_WorkWinThread определён в  CControlDlg
    m_WorkWinThread= AfxBeginThread(CControlDlg::GetFrame,this);
}

Код

void CControlDlg::OnPause()
{
    global_flag=true;
    ::WaitForSingleObject(m_WorkWinThread->m_hThread, INFINITE);//ну и тут не может дождаться завершения треда
    //причем непонятно работает ли при это сам тред, такое ощущение что нет
}


Код

CControlDlg::GetFrame()
{
   for..
   for..
    if(global_flag==true) //т.е. сюда почему то не доходит, а всё виснет похоже на WaitForSingleObject
      {
         return 0;
      }    
}


а если WaitForSingleObject убрать то доходит до строчки  
Цитата

if(global_flag==true)

но дело в том, что на завершения треда нужно некоторое время и если закрыть окно до того как он завершится то будет мемори лик.
т.е. проблема в том, что мне надо дождаться завершения треда, хотя наверно можно сделать кнопку закрыть неактивной, до того ка кон завершится , но это помоему не особо вариант.
PM MAIL   Вверх
mrgloom
Дата 6.7.2012, 14:48 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 829
Регистрация: 8.6.2011

Репутация: нет
Всего: нет



http://forums.codeguru.com/showthread.php?...to-end-a-thread

делал всё как тут, всё равно не хочет заходить в условие 
Код

if(::WaitForSingleObject(pthis->m_StopThread, 0) == WAIT_OBJECT_0)


а виснет на

Код

// Wait until thread finished
::WaitForSingleObject(m_WaitThread, INFINITE); 

PM MAIL   Вверх
Dem_max
Дата 6.7.2012, 16:07 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1780
Регистрация: 12.4.2007

Репутация: 1
Всего: 39



INFINITE говорит что ожидать события бесконечно пока поток не завершится

Добавлено через 1 минуту и 23 секунды
WaitForSingleObject(myWinThread,MAX_TIME_TO_WAIT_THREAD); //почему не ждем?
ждет на время  MAX_TIME_TO_WAIT_THREAD при условии что поток не завершен и myWinThread валиден.


--------------------
Американские программисты долго не могли понять, почему русские при зависании Windоws всё время повторяют "Твой зайка написал" ("Yоur bunnу wrоte")
PM MAIL   Вверх
mrgloom
Дата 9.7.2012, 09:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 829
Регистрация: 8.6.2011

Репутация: нет
Всего: нет



Цитата(Dem_max @  6.7.2012,  16:07 Найти цитируемый пост)
INFINITE говорит что ожидать события бесконечно пока поток не завершится

Добавлено через 1 минуту и 23 секунды
WaitForSingleObject(myWinThread,MAX_TIME_TO_WAIT_THREAD); //почему не ждем?
ждет на время  MAX_TIME_TO_WAIT_THREAD при условии что поток не завершен и myWinThread валиден. 



да, это то я понял, мне и нужно пока поток не завершится,  но такое ощущение, что происходит дедлок прям на WaitForSingleObject, только почему не ясно.

Добавлено @ 09:30
т.е. еще раз повторюсь такое ощущение, что при WaitForSingleObject всё замирает на нём и в треде ничего не выполняется, если же убрать 
Код

::WaitForSingleObject(m_WaitThread, INFINITE);
, а просто оставить 
Код

::SetEvent(m_StopThread);
 
то в ветку  в треде заходит, но дело, то в том, что надо подождать пока он завершится в основном потоке ,а этого сделать не получается.
Код

            if(::WaitForSingleObject(pthis->m_StopThread, 0) == WAIT_OBJECT_0)
            {

                // Set event
                ::SetEvent(pthis->m_WaitThread);

                LogMsg(_T("return from thread \r\n"));
                return 0;
            }


Это сообщение отредактировал(а) mrgloom - 9.7.2012, 09:32
PM MAIL   Вверх
mrgloom
Дата 9.7.2012, 11:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 829
Регистрация: 8.6.2011

Репутация: нет
Всего: нет




попробовал так же 

Код

while(::WaitForSingleObject(m_WaitThread, 0)!= WAIT_OBJECT_0)
            Sleep(1000);


так же на брекпоинт в треде не заходит, причем ни на какой.
PM MAIL   Вверх
mrgloom
Дата 10.7.2012, 12:04 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 829
Регистрация: 8.6.2011

Репутация: нет
Всего: нет



всё таки я не понял как работать с этим кодом для прерывания

http://www.tenouk.com/visualcplusmfc/visualcplusmfc22.html
Код

MSG message;
if (::PeekMessage(&message, NULL, 0, 0, PM_REMOVE))
{
    ::TranslateMessage(&message);
    ::DispatchMessage(&message);
}

PM MAIL   Вверх
Dem_max
Дата 12.7.2012, 06:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1780
Регистрация: 12.4.2007

Репутация: 1
Всего: 39



Не париться, вынести все вычисления в поток и окно не будет зависать.
Все легко и просто.


--------------------
Американские программисты долго не могли понять, почему русские при зависании Windоws всё время повторяют "Твой зайка написал" ("Yоur bunnу wrоte")
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Visual C++/MFC/WTL | Следующая тема »


 




[ Время генерации скрипта: 0.0556 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.