Легенда:
   новое сообщение
    закрытая нитка
    новое сообщение
    в закрытой нитке
    старое сообщение
         
		 | 
- Напоминаю, что масса вопросов по функционированию форума снимается после прочтения его описания.
 - Новичкам также крайне полезно ознакомиться с данным документом.
   
  |   |   |   |   |   |   |   | 
А через указатель тож никак?  10.11.03 15:36  Число просмотров: 1558
 Автор: CrazyPitbull Статус: Незарегистрированный пользователь
 | 
 
| 
 Я о другом, когда программа работает, если я буду работать с интерфейсом, то когда я из процесса обращаюсь к одному из компонентов, вылетает исключение, это нужно делать через Sinhronise? если да, то как?
 | 
 
| 
<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. И кстати что означает - "Весь интерфейс и визуализация - снаружи потока."?
 | 
 
 
  
 
 | 
 |