информационная безопасность
без паники и всерьез
 подробно о проектеRambler's Top100
За кого нас держат?Портрет посетителя
BugTraq.Ru
Русский BugTraq
 Анализ криптографических сетевых... 
 Модель надежности двухузлового... 
 Специальные марковские модели надежности... 
 Бэкдор в xz/liblzma, предназначенный... 
 Три миллиона электронных замков... 
 Doom на газонокосилках 
главная обзор RSN блог библиотека закон бред форум dnet о проекте
bugtraq.ru / форум / programming
Имя Пароль
ФОРУМ
если вы видите этот текст, отключите в настройках форума использование JavaScript
регистрация





Легенда:
  новое сообщение
  закрытая нитка
  новое сообщение
  в закрытой нитке
  старое сообщение
  • Напоминаю, что масса вопросов по функционированию форума снимается после прочтения его описания.
  • Новичкам также крайне полезно ознакомиться с данным документом.
[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. И кстати что означает - "Весь интерфейс и визуализация - снаружи потока."?
1  |  2 >>  »  




Rambler's Top100
Рейтинг@Mail.ru


  Copyright © 2001-2024 Dmitry Leonov   Page build time: 0 s   Design: Vadim Derkach