С ним всякие глюки иногда бывают не очень понятные и если его засунуть в неудачное место может получится его рекурсивный вызов самого себя. Я обычно делаю BeginThread (с CreateThread могут быть проблемы с работой с динасический памятю из разных потоков) затем ставлю оюработчик сообщений на какоенить окно и свойства VCL'ных объектов из потоков меняю вызовом SendMessage у которого wParam - код функции а lParam -указатель на структуру параметров. Затем обертываю весь обработчик в try..catch и если у юзера вылетел глюк то ему показывается что где и когда.
[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. В принципе, можно завести глобальную переменную под это дело.
С ним всякие глюки иногда бывают не очень понятные и если его засунуть в неудачное место может получится его рекурсивный вызов самого себя. Я обычно делаю 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
> Проблема такая, программа обрабатывает данные и > одновременно с обработкой должна быть возможность работы с > интерфейсом... Как это сделать? Насколько я понимаю Насколько я помню, как раз цикл 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 Статус: Незарегистрированный пользователь
Который реализован через 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? если да, то как?
> Кроме того, если все таки воспользуешься TThread-ом советую > посмотреть в описание его member-функций. Я его юзал давно > (лет 5 назад), но что то такое там точно есть
Совершенно точно. Сам я юзал тоже давно. Но вроде всё получалось в BCB++.
А в части примеров(квуик старт), см. в папке
C:\Program Files\Borland\CBuilder6\Examples\Apps\Threads
PS. Я б стал копать API, позже, когда бы увител что класса TThread от BCB++
уже недостаточно.
CreateThread - это оно и есть. У меня так работает счетная программа для моделирования полимеризации, сделанная из Buildera.
Могу для примера привести кусочек.