Посоветуйте как сделать
Программой обрабатываю большое кол-во файлов цыкл, соответственно это занимает длительный процесс, нужно сделать так чтобы ход процесса отображался в новом окне через ProgressBar
Делал сам, но
for(int i=0;i<FileCount;i++)
{
...
// обработка файла
...
ProgressBar->Position = 100*i/FileCount;
}
дает плохой результат(окно как бы подвисает), говорят что необходимо делать через потоки, но тут тоже сам не могу додуматься
направьте, куда копать как построить связь ProgressBar'а и текущего файла
К сожалению опыта не так много потом прошу помощи:
Программой обрабатываю большое кол-во файлов цыкл, соответственно это занимает длительный процесс, нужно сделать так чтобы ход процесса отображался в новом окне через ProgressBar
Делал сам, но
for(int i=0;i<FileCount;i++)
{
...
// обработка файла
...
ProgressBar->Position = 100*i/FileCount;
}
дает плохой результат(окно как бы подвисает), говорят что необходимо делать через потоки, но тут тоже сам не могу додуматься
направьте, куда копать как построить связь ProgressBar'а и текущего файла
Лучше, конечно, в таком случае обработку вынести в отдельный поток и вместо
ProgressBar->Position = 100*i/FileCount;
посылать сообщение главному окну, и в обработчике уже менять Positions.
Можно обойтись и без сообщений и напрямую, но я предпочитаю через сообщения такие вещи делать, т.к. все контролируешь сам, а не Синхронайз непонятно чего там делает
Другой вопрос, что
// обработка файла
непонятно и возможно это вынести в поток довольно геморно, и тогда ПргрессБар надо на отдельном окне вынести в другой поток.
Вобщем резюме такое, что без разных потоков не обойтись полюбому, если действительно хочешь красиво сделать
дает плохой результат(окно как бы подвисает), говорят что необходимо делать через потоки, но тут тоже сам не могу додуматься
Можно попробовать:
{
...
// обработка файла
...
ProgressBar->Position = 100*i/FileCount;
ProgressBar->Update();
// или Application->ProcessMessages();
}
Если использовать второй подход (Application->ProcessMessages), будет больше геморроя с запрещением контролов, чтобы пользователь не мог запустить цикл обработки второй раз. Зато можно будет добавить проверку значения, не прервал ли пользователь процесс обработки, и организовать прерывание цикла.
На практике делалось уже много раз. Все прекрасно работает и без потоков.
Можно попробовать:
{
...
// обработка файла
...
ProgressBar->Position = 100*i/FileCount;
ProgressBar->Update();
// или Application->ProcessMessages();
}
Если использовать второй подход (Application->ProcessMessages), будет больше геморроя с запрещением контролов, чтобы пользователь не мог запустить цикл обработки второй раз. Зато можно будет добавить проверку значения, не прервал ли пользователь процесс обработки, и организовать прерывание цикла.
На практике делалось уже много раз. Все прекрасно работает и без потоков.
Работает может и прекрасно - выглядит неочень по крайней мере на ХР.
Если все делать в одном потоке в длинном цикле с большим количествои итераций все будет хреново. Никакие рефреши, инвалидеты не спасут.
На практике делалось уже много раз.
Лучше, конечно, в таком случае обработку вынести в отдельный поток и вместо
ProgressBar->Position = 100*i/FileCount;
посылать сообщение главному окну, и в обработчике уже менять Positions.
Можно обойтись и без сообщений и напрямую, но я предпочитаю через сообщения такие вещи делать, т.к. все контролируешь сам, а не Синхронайз непонятно чего там делает
Другой вопрос, что
// обработка файла
непонятно и возможно это вынести в поток довольно геморно, и тогда ПргрессБар надо на отдельном окне вынести в другой поток.
Вобщем резюме такое, что без разных потоков не обойтись полюбому, если действительно хочешь красиво сделать
Да думаю что действительно лучше обработку вынести в отдельный поток,
// обработка файла
обработка файла это:
запуск внешнего приложения с передачей ей параметров командной строки и ожидания его завершения(ниже это есть)
т.е. я хочу перекодирывтаь файлы из wav в mp3 через программу lame.exe для чего зоздаю процесс CreateProcess(...)
вчера вечером вот что навоял,
главная форма:
void __fastcall TForm1::Button1Click(TObject *Sender)
{
Th *T= new Th(false);//открытие потока
T->FreeOnTerminate=true;
}
void __fastcall TForm1::OnProgMess(TMessage& a)
{
//по приходу сообщения(WM_PROGRESS) мызывается эта функция
ProgressBar1->Position=100*a.LParam/a.WParam;
}
Сам поток(Обработка файлов):
void __fastcall Th::Execute()
{
for(int i=0;i<5;i++)
{
STARTUPINFO StartInfo = {sizeof(TStartupInfo)};
PROCESS_INFORMATION ProcInfo;
LPCTSTR s;
StartInfo.cb=sizeof(StartInfo);
StartInfo.dwFlags=STARTF_USESHOWWINDOW;
StartInfo.wShowWindow=SW_MINIMIZE;
AnsiString ComandLine="lame.exe smels.mp3 test"+IntToStr(i)+".mp3";
CreateProcess(NULL,ComandLine.c_str(),NULL,NULL,false,NORMAL_PRIORITY_CLASS|CREATE_NEW_PROCESS_GROUP,NULL,NULL,&StartInfo,&ProcInfo);
switch(WaitForSingleObject(ProcInfo.hProcess,100000))
{
case WAIT_TIMEOUT:
{
SendMessage(FindWindow("TForm1","Form1"),WM_PROGRESS,5,i+1);
} break;
case WAIT_OBJECT_0:
{
SendMessage(FindWindow("TForm1","Form1"),WM_PROGRESS,5,i+1);
}break;
}// end switch
}// end for
}
Вот все это работает, сообщения отсылаюься когда нужно, прогрес бар меняется, но все равно главная форма тормозит, почему?
Я кажись не вижу где ты выделяешь время для основного потока. В цикле for на каждой итерации должно быть нечто типа
Sleep(100);
100 - я взял с потолка. Думаю, что эту функцию ты знаешь.
Я кажись не вижу где ты выделяешь время для основного потока. В цикле for на каждой итерации должно быть нечто типа
Sleep(100);
100 - я взял с потолка. Думаю, что эту функцию ты знаешь.
нет не занал такой функции, зачем она нужна в данном случае?
WaitForSingleObject(ProcInfo.hProcess,100000)
ждет либо завершения процесса hProcess либо завершает его по истечении 100000 мсек
а с зависанием окна разобрался сам, просто lame.exe имеет по умолчанию видимо наивысший приоритет, и ей еще нужно в командной строке посылать уровень приоритета, вобщем сейчас все работаетк как хотелось изначально! :)
нет не занал такой функции, зачем она нужна в данном случае?
Sleep(n)
говорит что поток, в котором она вызывается должен остановиться на n милисекунд. В это время работают другие потоки приложения. Т.е это не дает потоку полностью забрать ресурсы.
Еще я бы вместо SendMessage использовал PostMessage, хотя это не принципиально.
Sleep(n)
говорит что поток, в котором она вызывается должен остановиться на n милисекунд. В это время работают другие потоки приложения. Т.е это не дает потоку полностью забрать ресурсы.
Еще я бы вместо SendMessage использовал PostMessage, хотя это не принципиально.
может вместо использования Sleep расставить приоритеты у всех потоков, я расставил все паралельным потокам одинаковые нормальные приоритеты и все работает паралельно и ничего не тормозит.