Легенда:
новое сообщение
закрытая нитка
новое сообщение
в закрытой нитке
старое сообщение
|
- Напоминаю, что масса вопросов по функционированию форума снимается после прочтения его описания.
- Новичкам также крайне полезно ознакомиться с данным документом.
|
[C++] Поиск по форуму тоже рулит... 08.11.03 09:09 Число просмотров: 2113
Автор: HandleX <Александр М.> Статус: The Elderman
|
> Проблема такая, программа обрабатывает данные и > одновременно с обработкой должна быть возможность работы с > интерфейсом... Как это сделать? Насколько я понимаю > необходимо запустить новый поток для обработки данных, > тогда программа висеть не будет? Пишу в Builder'e. Если > можно посмотреть исходники какие или есть дока по данной > теме буду очень благодарен. Заранее спасибо!
Потоки дело сурьёзное...
Часто выгода от них призрачная...
Если нужно, чтобы интерфейс приложения не висел во время обработки данных, тебе может помочь Application->ProcessMessages().
Пример (на Delphi, но ты поймёшь, imho)
procedure TForm1.Button1Click(Sender: TObject);
begin
If Button1.Tag <> 0 Then
Begin
Button1.Tag := 0;
Exit;
End;
Button1.Caption := 'Stop';
Repeat
Button1.Tag := Button1.Tag + 10;
Caption := IntToStr(Button1.Tag);
Application.ProcessMessages;
sleep(100);
Until Button1.Tag = 0;
Button1.Caption := 'Start';
Caption := '0';
end;
Суть примера поясняю — эдакий старт-стоповый таймер на одной кнопке с циклом обработки без потоков ;-) Ключевой элемент, используемый для отсановки обработки - поле TButton.Tag. В принципе, можно завести глобальную переменную под это дело.
Смотри тута. Читай все ветки ;-)
|
<programming>
|
[C++] Как запустить в программе паралельный поток обработки данных? 07.11.03 20:21 [Ktirf]
Автор: CrazyPitbull Статус: Незарегистрированный пользователь
|
Проблема такая, программа обрабатывает данные и одновременно с обработкой должна быть возможность работы с интерфейсом... Как это сделать? Насколько я понимаю необходимо запустить новый поток для обработки данных, тогда программа висеть не будет? Пишу в Builder'e. Если можно посмотреть исходники какие или есть дока по данной теме буду очень благодарен. Заранее спасибо!
|
|
[C++] Поиск по форуму тоже рулит... 08.11.03 09:09
Автор: HandleX <Александр М.> Статус: The Elderman
|
> Проблема такая, программа обрабатывает данные и > одновременно с обработкой должна быть возможность работы с > интерфейсом... Как это сделать? Насколько я понимаю > необходимо запустить новый поток для обработки данных, > тогда программа висеть не будет? Пишу в Builder'e. Если > можно посмотреть исходники какие или есть дока по данной > теме буду очень благодарен. Заранее спасибо!
Потоки дело сурьёзное...
Часто выгода от них призрачная...
Если нужно, чтобы интерфейс приложения не висел во время обработки данных, тебе может помочь Application->ProcessMessages().
Пример (на Delphi, но ты поймёшь, imho)
procedure TForm1.Button1Click(Sender: TObject);
begin
If Button1.Tag <> 0 Then
Begin
Button1.Tag := 0;
Exit;
End;
Button1.Caption := 'Stop';
Repeat
Button1.Tag := Button1.Tag + 10;
Caption := IntToStr(Button1.Tag);
Application.ProcessMessages;
sleep(100);
Until Button1.Tag = 0;
Button1.Caption := 'Start';
Caption := '0';
end;
Суть примера поясняю — эдакий старт-стоповый таймер на одной кнопке с циклом обработки без потоков ;-) Ключевой элемент, используемый для отсановки обработки - поле TButton.Tag. В принципе, можно завести глобальную переменную под это дело.
Смотри тута. Читай все ветки ;-)
|
| |
не очень я люблю ProcessMessages 08.11.03 09:36
Автор: Killer{R} <Dmitry> Статус: Elderman
|
С ним всякие глюки иногда бывают не очень понятные и если его засунуть в неудачное место может получится его рекурсивный вызов самого себя. Я обычно делаю BeginThread (с CreateThread могут быть проблемы с работой с динасический памятю из разных потоков) затем ставлю оюработчик сообщений на какоенить окно и свойства VCL'ных объектов из потоков меняю вызовом SendMessage у которого wParam - код функции а lParam -указатель на структуру параметров. Затем обертываю весь обработчик в try..catch и если у юзера вылетел глюк то ему показывается что где и когда.
|
| | |
Ну как-бы гибкость тоже должна быть ;-) 08.11.03 09:50
Автор: HandleX <Александр М.> Статус: The Elderman
|
> С ним всякие глюки иногда бывают не очень понятные и если > его засунуть в неудачное место может получится его > рекурсивный вызов самого себя. Я обычно делаю BeginThread > (с CreateThread могут быть проблемы с работой с > динасический памятю из разных потоков) затем ставлю > оюработчик сообщений на какоенить окно и свойства VCL'ных > объектов из потоков меняю вызовом SendMessage у которого > wParam - код функции а lParam -указатель на структуру > параметров. Затем обертываю весь обработчик в try..catch и > если у юзера вылетел глюк то ему показывается что где и > когда. Я про простые случаи имел ввиду.
Пусть автор поста знает все возможные варианты...
В потоках тоже могут быть всякие трудновоспринимаемые глюки... Особенно если учесть, что TForms и прочие гуевые библиотеки плохо переносят многопоточность. С использованием TThread тоже достаточно гемора можно поймать.
Короче, всё это на любителя. Пусть автор поста станет гибче в своих решениях и знает про все фичи.
|
| | | |
Ну так SendMessage как раз против глюков в потоках 08.11.03 09:57
Автор: Killer{R} <Dmitry> Статус: Elderman
|
> Я про простые случаи имел ввиду. > Пусть автор поста знает все возможные варианты... Ну да в принципе если ему просто построить график какой нибудь то ProcessMessages самое то
> В потоках тоже могут быть всякие трудновоспринимаемые > глюки... Особенно если учесть, что TForms и прочие гуевые > библиотеки плохо переносят многопоточность. SendMessage посылает сообщение основному потоку и ждет завершения его обработки - и глюков никаких. Правда конечно не совсем красиво вызывать какуюто другую функцию которая к примеру добавляет TListItem через SendMessage зато не глючит
|
| | | | |
Ok. 08.11.03 10:08
Автор: HandleX <Александр М.> Статус: The Elderman
|
|
|
[C++] Все таки RTFM рулит 08.11.03 00:53
Автор: amirul <Serge> Статус: The Elderman
|
> Проблема такая, программа обрабатывает данные и > одновременно с обработкой должна быть возможность работы с > интерфейсом... Как это сделать? Насколько я понимаю Насколько я помню, как раз цикл GetMessage/DispatchMessage как раз и запускается отдельным тредом (по крайней мере так в MFC, в vcl скорее всего тоже), в основном (который WinMain) же можно делать что угодно. Если же действительно нужен новые тред, то нужно отнаследоваться от класс TThread (кажется так) и переопределить виртальную функцию Execute. Тогда по new TMyThread будет создаваться поток, исполняющий данную функцию, в деструкторе (delete) он будет уничтожаться.
Кроме того, как уже упоминалось советую CreateThread.
> можно посмотреть исходники какие или есть дока по данной > теме буду очень благодарен. Заранее спасибо! Дока - это билдеровский хелп.
ЗЫ: Насколько я понимаю, если возник вопрос по созданию потоков, следующий вопрос будет по их синхронизации. Сразу отвечу, что тема эта достаточно обширная и помочь может только тщательный RTFM
Основные виды синхронизации:
1) Разделяемая память: ну это понятно. Контекст памяти у разных потоков для одного процесса один, так что никаких дополнительных извращений не надо
2) Event-ы (события): CreateEvent и сопутствующие - за дополнительной инфой в MSDN
3) Mutex-ы (mutually exclusive - взаимно исключающие) CreateMutex и остальные, описание в MSDN
4) Semaphore-ы (семафоры) CreateSemaphore ...
5) Named Pipe-ы (именованные потоки) CreateNamedPipe (CreateFile тоже умеет их создавать) ...
Кроме того, если все таки воспользуешься TThread-ом советую посмотреть в описание его member-функций. Я его юзал давно (лет 5 назад), но что то такое там точно есть
|
| |
[C++] Неплохо... но как переопределить Execute? 08.11.03 15:24
Автор: CrazyPitbull Статус: Незарегистрированный пользователь
|
Вроде наплохо с TThread'oм работать. Я отнаследовал создал свою функцию оюработки, но немогу переопределить Execute, нужно передать указатель на мою функцию или что?
|
| | |
[C++] Просто переопределить 08.11.03 16:49
Автор: amirul <Serge> Статус: The Elderman
|
> Вроде наплохо с TThread'oм работать. Я отнаследовал создал > свою функцию оюработки, но немогу переопределить Execute, > нужно передать указатель на мою функцию или что? В vcl записано примерно следующее
class TThread {
//...
protected:
void Execute(аргументы);
};
void TThread::Execute(аргументы) {
// stub
}
Ты делаешь
class TMyThread {
protected:
virtual void Execute(аргументы);
};
void TMyThread::Execute(аргументы) {
// Здесь тело твоего потока (функция, которая будет исполняться в новом потоке)
}
Главное следи, чтобы типы аргументов совпадали, иначе ты не переопределишь, а перегрузишь (читай введешь еще одну функцию) функцию Execute.
А вообще почитай про работу с виртуальными функциями.
|
| | | |
[C++] Так и сделал, но иногда глючит... 09.11.03 02:33
Автор: CrazyPitbull Статус: Незарегистрированный пользователь
|
Так и сделел, вроди работает, если не трогать окно программы, а если поработать с интерфейсом, то после завершения задачи выкидывает исключение...
|
| | | | |
А вот для работы с интерфейсом у TThread есть метод Synchronize 09.11.03 09:44
Автор: Killer{R} <Dmitry> Статус: Elderman
|
Который реализован через SendMessage. Нельзя из других потоков обращаться к VCL компонентам, будут именно такие глюки. В хелпе кстати об этом написано.
|
| | | | | |
А через указатель тож никак? 09.11.03 12:24
Автор: CrazyPitbull Статус: Незарегистрированный пользователь
|
Вот какая досада, как раз нужно обращаться к одному из компанентов... Чтож делать? Мож обойти как можно или есть какий хитрый счпособ? Я пробовал в отнаследованном классе создавать указатель на компонент, а в конструкторе пихал в него адрес того к которому нужно обратиться, но опять вылетает исключение!
|
| | | | | | |
А через указатель тож никак? 09.11.03 13:05
Автор: Killer{R} <Dmitry> Статус: Elderman Отредактировано 09.11.03 13:18 Количество правок: 3
|
Во первых прежде чем закрывать свою прогу надо остановить поток. Во вторых я не очень понял что именно ты хочешь обходить хитрым способом и при чем тут указатель? Там вроде везде к VCL классам обращение через указатели делается. Просто если хочешь изменить например текст в каком нибудь EditBox'е то вызываешь в Synchronize процедуру которая его меняет и все.
|
| | | | | | | |
А через указатель тож никак? 10.11.03 15:36
Автор: CrazyPitbull Статус: Незарегистрированный пользователь
|
Я о другом, когда программа работает, если я буду работать с интерфейсом, то когда я из процесса обращаюсь к одному из компонентов, вылетает исключение, это нужно делать через Sinhronise? если да, то как?
|
| | | | | | | | |
А хелпы читать гордость мешает? 10.11.03 17:45
Автор: Killer{R} <Dmitry> Статус: Elderman
|
Цитирую:
This example shows how to call a button’s click method in a thread-safe manner:
void __fastcall TMyThread::PushTheButton(void)
{
Button1->Click();
}
void __fastcall TMyThread::Execute()
{
...
Synchronize(PushTheButton);
...
}
|
| | | |
А мона еще проще 08.11.03 17:37
Автор: Killer{R} <Dmitry> Статус: Elderman
|
File->New->Other->Thread Object хотя имхо BeginThread еще проще Ж)
|
| |
[C++] Все таки RTFM рулит 08.11.03 02:16
Автор: void <Grebnev Valery> Статус: Elderman
|
> Кроме того, если все таки воспользуешься TThread-ом советую > посмотреть в описание его member-функций. Я его юзал давно > (лет 5 назад), но что то такое там точно есть
Совершенно точно. Сам я юзал тоже давно. Но вроде всё получалось в BCB++.
А в части примеров(квуик старт), см. в папке
C:\Program Files\Borland\CBuilder6\Examples\Apps\Threads
PS. Я б стал копать API, позже, когда бы увител что класса TThread от BCB++
уже недостаточно.
|
|
[C++] Ключевые слова - threads, multithreading 07.11.03 22:11
Автор: Ktirf <Æ Rusakov> Статус: Elderman
|
Можно также посмотреть документацию на WinAPIшный вызов CreateThread (и его близких родственников).
|
| |
[C++] CreateThread - это оно и есть. 10.11.03 20:13
Автор: vagrant Статус: Незарегистрированный пользователь
|
CreateThread - это оно и есть. У меня так работает счетная программа для моделирования полимеризации, сделанная из Buildera.
Могу для примера привести кусочек.
По кнопочке запускается обработчик
void __fastcall TRCDesk::btStartProcessClick(TObject *Sender)
{
if(Indicator==0)
{btStartProcess->Enabled=false; Indicator=1;
btKillProcess->Enabled=true; IndRotation=1;
//-----------------------------------------------------------------
RIVTr1=CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) ReactorIV_Thread,
(LPVOID)NULL, THREAD_SUSPEND_RESUME, &Tid);
lstEvent=CreateEvent(NULL,false,false,"lst"); lst=1; ltime_ind=0;
//-------------------------------------------------------------------
btLife->Enabled=true;
AttrX = GetSystemMetrics(SM_CXFULLSCREEN);
AttrY = GetSystemMetrics(SM_CYFULLSCREEN);
TrackBarX->Position=-alphaVolume;
TrackBarY->Position=-betaVolume;
TrackBarZ->Position=-gammaVolume;
sc=long(float(AttrY)/1.732/float(L.x));
};
}
котрый и запускает процесс ReactorIV_Thread
DWORD ReactorIV_Thread(LPVOID param);
DWORD Tid;
HANDLE RIVTr1; HANDLE lstEvent;
DWORD
ReactorIV_Thread(LPVOID param)
{
...здесь все вычисления
}
если надо убить процес, запускаем функцию TerminateThread(RIVTr1,NULL);
Работает все надежно, как лопата.
Весь интерфейс и визуализация - снаружи потока.
|
| | |
А в лопате есть потенциальный баг 11.11.03 01:42
Автор: Killer{R} <Dmitry> Статус: Elderman
|
CreateThread в билдере лучше не юзать а вместо него юзать BeginThread. И кстати что означает - "Весь интерфейс и визуализация - снаружи потока."?
|
|
|