Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "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.033 c
3-1094751452
radiant09
2004-09-09 21:37
2004.10.10
перетаскивание записей в dbgrid e


3-1094463982
Alex Z
2004-09-06 13:46
2004.10.10
Вызов хранимых процедур из Делфи! ПРОБЛЕМЫ!!!


3-1094627732
yuray
2004-09-08 11:15
2004.10.10
Инфо о клиентах базы


1-1096360969
Charly22
2004-09-28 12:42
2004.10.10
TSpeedButton


4-1094474007
edthon
2004-09-06 16:33
2004.10.10
СОМ-порт, задержка между командами





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский