Форум: "WinAPI";
Текущий архив: 2004.10.10;
Скачать: [xml.tar.bz2];
ВнизОбмен данными между потоками не используя главную форму! Найти похожие ветки
← →
Apolo © (2004-09-10 10:44) [0]Здраствуйте мастера!
У меня есть потоки, которые считают одним алгоритмом, только у каждого разные входные данные и ясное дело разные выходные данные.
Потоков может быть куча и по коду они идентичны!
Мне надо создать еще один поток, в котором будут обрабатываться промежуточные выходные данные предыдущих потоков.
Вопрос таков:
Как сделать обмен между потоками, не используя главной формы? Точнее - как мне из одного потока добраться до переменных различного типа другого потока?
Заранее спасибо.
← →
panov © (2004-09-10 10:47) [1]Уточни вопрос - используешь потоки только в WinApi или класс-обертку TThread?
← →
Apolo © (2004-09-10 10:58) [2]
> Уточни вопрос - используешь потоки только в WinApi или класс-обертку
> TThread?
а в чем разница?
Вот код моих идентичных потоков:unit TestThread;
interface
uses
Classes, SysUtils;
type
TTestThread = class(TThread)
private
{ Private declarations }
Answer : integer;
protected
procedure Execute; override;
end;
implementation
uses mainunit;
procedure TTestThread.Execute;
var i: integer;
begin
FreeOnTerminate := True;
Answer:=0;
// Здесь делаем чтото и периодически промежуточный ответ в Answer записываем!
// Answer - ето пример, переменых намного больше будет!
end;
end.
Вот мне надо создать еще один поток, который будет у каждого из предыдущих спрашивать промежуточное значение Answer и делать чтото!
Из основного модуля, если надо, я их запускаю так:unit mainunit;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, TestThread;
type
............
............
implementation
{$R *.dfm}
procedure TForm1.Button1Click(Sender: TObject);
var NewThread: TTestThread;
begin
.............
NewThread := TTestThread.Create(False);
.............
end;
← →
Polevi © (2004-09-10 10:58) [3]>panov © (10.09.04 10:47) [1]
какая разница ?
>Apolo © (10.09.04 10:44)
рабочие потоки должны уведомлять " поток, в котором будут обрабатываться промежуточные выходные данные предыдущих потоков" о том что "промежуточные данные" готовы для обработки ии лежат в определенном месте
для уведомлений см. PostThreadMessage, WaitForXXX, MsgWaitForXXX, Event, Semaphore, Mutex, CriticalSection итд
← →
Apolo © (2004-09-10 11:14) [4]
> рабочие потоки должны уведомлять
как? можно пример?
(единственное ограничение - уведомление не должно быть синхронным)
> "промежуточные данные" готовы для обработки
нету понятия у меня готовы! на то они и промежуточные.. мне надо взять данные на данный момент времени и не волнует, успел он пощитать или нет!
> и лежат в определенном месте
Думал уже file-mapping делать и тд...
если integer, то можно еще там найти нужные 4 байтика!
а если мне передавать тип запись, где можно голову сломать, пока найдешь в file-mapping где его каждое значение!
← →
Polevi © (2004-09-10 11:19) [5]>как? можно пример?
PostMessage, PostThreadMessage, SetEvent, ReleaseSemaphore, ReleaseMutex
готовы не готовы - без разницы.. главное есть что обратобать
с помощью PostMessage, PostThreadMessage можешь передавать указатель на данные, если глобальный список защищеный критической секцией не устраивает
← →
panov © (2004-09-10 11:21) [6]А разница в том, что для класса TThread совсем необязательно использование напрямую объектов синхронизации.
Кроме этого, вопросы, связанные с VCL, задаются(как правило) в основной конференции.
Теперь, по поводу [1] и Apolo © (10.09.04 10:58) [2]
Для конкретного случая из [2] один из вариантов может быть таким:
Сначала создается поток, который должен обрабатывать результаты, в нем(в public или private-секции) создается массив для получения результатов от дочерних потоков.
Затем возможны 2 варианта:
- в дочернем потоке создается переменная для хранения результатов вычислений, которую прочитывает основной поток после завершения дочернего;
- дочерний поток сам записывает результат в основной поток после своего завершения.
Определения завешения комплекса вычислений может быть реализовано тоже несколько вариантов, например, такой:
В основном потоке вводится счетчик количества этапов.
После запуска всех дочерних потоков основной поток засыпает.
При завершении каждого дочернего потока основной поток пробуждается, уменьшает счетчик и проверяет его.
После обнуления счетчика основной поток обрабатывает результаты.
Вот, в общем-то, и все.
← →
panov © (2004-09-10 11:23) [7]нету понятия у меня готовы! на то они и промежуточные.. мне надо взять данные на данный момент времени и не волнует, успел он пощитать или нет!
Так вроде бы нет проблем...
← →
Digitman © (2004-09-10 11:31) [8]
> Apolo
можно поступить так (в контексте дан.примера) :
unit TestThread;
interface
uses
Classes, SysUtils;
type
TTestThread = class(TThread)
private
{ Private declarations }
protected
procedure Execute; override;
procedure AfterConstruction; override;
procedure BeforeDestruction; override;
public
Answer : integer;
CS: TCriticalSection;
end;
implementation
uses mainunit;
procedure TTestThread.AfterConstruction;
begin
CS := TCriticalSection.Create;
end;
procedure TTestThread.BeforeDestruction;
begin
CS.Free;
end;
procedure TTestThread.Execute;
var i: integer;
begin
while CS = 0 do sleep(0);
..
cs.Enter;
try
Answer := ...;
finally
cs.Leave;
end;
..
end;
...
//модуль формы
procedure TForm1.Button1Click(Sender: TObject);
var NewThread: TTestThread;
begin
.............
NewThread := TTestThread.Create(False);
.............
with NewThread do
begin
cs.Enter;
try
ShowMessage(IntToStr(Answer));
finally
cs.Leave;
end;
end;
end;
← →
Apolo © (2004-09-10 11:41) [9]
> с помощью PostMessage, PostThreadMessage можешь передавать
> указатель на данные
1. можно пример?
2. Если отправил сообщение, а предыдушее еще не успело отработать - они не потеряються?
3. Если я передаю указатель не на переменную а на "тип запись" - ошибок не будет? как лучше в етом случае?
> если глобальный список защищеный критической секцией не
> устраивает
может быть и устроил.. тока вот в хелпе по CriticalSection у меня, к сожалению, ничего нету!
← →
Apolo © (2004-09-10 11:47) [10]
> Digitman © (10.09.04 11:31) [8]
Вот ето то, что мне надо! ... Большое спасибо!
Найду щас описание CriticalSection и буду внедрять!
Спасибо всем!
← →
Apolo © (2004-09-10 12:02) [11]
while CS = 0 do sleep(0);
..
cs.Enter;
try
Answer := ...;
finally
cs.Leave;
end;
Т.е я считаю значения и пишу в какую-то другую переменную (не Answer), а когда я хочу опубликовать ее значение, я использую твой блок (Записываю в Answer нужное значение)! while CS = 0 do sleep(0) - значит ждать пока ктото другой не закончит работу с переменной!... Так?
← →
Digitman © (2004-09-10 12:34) [12]
> Т.е я считаю значения и пишу в какую-то другую переменную
> (не Answer), а когда я хочу опубликовать ее значение, я
> использую твой блок (Записываю в Answer нужное значение)!
>
нет.
попытка и чтения и записи Answer (или сто там у тебя будет вместо нее) со стороны ЛЮБОГО трэда д.б. заключена в блок
cs.Enter; //входи в крит.секцию
try
.. ЗДЕСЬ читаем или пишем переменную, и в этот момент ни один другой трэд не имеет на это права (ждет)
finally
cs.Leave; //выходим из крит.секции
end;
> while CS = 0 do sleep(0) - значит ждать пока ктото другой
> не закончит работу с переменной!... Так?
не так.
крит.секция в дан.случае создается осн.трэдом (т.е. тем который вызвал конструктор доп.трэда)
в рез-те доп.тред стартует еще ДО того как будет выполнен метод AfterConstruction, в котором собссно и создается крит.секция
поэтому доп.поток должен подождать, пока осн.поток создаст объект-крит.секцию, прежде чем обратиться к ней
← →
Apolo © (2004-09-10 12:57) [13]Хорошо а чем тогда оличаеться критическая секция от семафоры? По сути дела, как я понял, он делают одно и тоже!
← →
Lin7 (2004-09-10 13:13) [14]
> Apolo © (10.09.04 12:57) [13]
Синхронизация потоков хорошо описана у Рихтера.
http://alexsoft.home.nov.ru/download/prog/
← →
Digitman © (2004-09-10 13:22) [15]
> Apolo © (10.09.04 12:57) [13]
> чем .. оличаеться критическая секция от семафоры?
> По сути дела, как я понял, он делают одно и тоже!
нет, делают они некоторым образом разное, но предназначены для одной и той же цели - синхронизации доступа к ресурсам в мультипоточной среде
крит.секция идеально подходит для синхр-ции в контексте одного и того же процесса, но никак не подходит для синхр-ции в контексте более чем одного процесса ... работает быстро, в момент ожидания пытающийся войти в секцию трэд "слеп" и "глух" - не может реагировать ни на какие события/сообщения
семафор более подходит для интерпроцессной защиты ресурса, работает медленней крит.секции, в момент ожидания "семафора" трэд способен реагировать на события/сообщения
← →
Erik1 (2004-09-10 14:20) [16]Вобщето по большому секрету могу сказать, что есть глубоко зарытая борландовский класс TMultiReadExclusiveWriteSynchronizer
Он делает всю работу за тебя, вроде доброй феи. Ты только ему скажи:
FLock: TMultiReadExclusiveWriteSynchronizer;
..........
FLock.BeginWrite;
try
MyAnswer.TaTaTa := $FF;
MyAnswer.Value := "Ура пишем";
finally
FLock.EndWrite;
end;
Как читать думаю догодаешся, незубудь что читать всеми тредами лучше через одну процедуру.
Страницы: 1 вся ветка
Форум: "WinAPI";
Текущий архив: 2004.10.10;
Скачать: [xml.tar.bz2];
Память: 0.5 MB
Время: 0.036 c