Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2004.10.10;
Скачать: CL | DM;

Вниз

Обмен данными между потоками не используя главную форму!   Найти похожие ветки 

 
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 вся ветка

Текущий архив: 2004.10.10;
Скачать: CL | DM;

Наверх




Память: 0.52 MB
Время: 0.04 c
14-1095508040
Программер_
2004-09-18 15:47
2004.10.10
Вот привожу код и пусть кто мне сможет сказать что нем


4-1094015053
HeKTO
2004-09-01 09:04
2004.10.10
Проводник (explorer)


1-1096264614
Никита
2004-09-27 09:56
2004.10.10
Поиск в строке


1-1095888698
Константинов
2004-09-23 01:31
2004.10.10
Подскажите, как правильно работать со свойствами-массивами


14-1095948626
Nikolay M.
2004-09-23 18:10
2004.10.10
Масяня вернулась!