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

Вниз

Передача параметра из потока   Найти похожие ветки 

 
ksa2002   (2005-08-15 18:53) [0]

Вопрос такой
есть процедура в главном потоке
f_main;
её вызывает поток  1-й
Synchronize(f_main);
и её вызывает поток  2-й
Synchronize(f_main);
------------------------------
можно ли сделать так

f_main (s:string);
её вызывает поток  1-й
Synchronize(f_main("1"));
и её вызывает поток  2-й
Synchronize(f_main("2"));
т.е. вызвать её с параметром?


 
troits ©   (2005-08-15 19:00) [1]

Нет, так явно нельзя, поскольку параметр Synchronize, TThreadMethod жестко описан как procedure of object. Для передачи параметров надо воспользоваться какой-нибудь переменной, видимой из f_main.


 
troits ©   (2005-08-15 19:07) [2]

Кстати, заполнение этих переменных надо "обезопасить", например, критическими секциями.


 
ksa2002   (2005-08-15 19:17) [3]

хех ...так она работает))) мне интересно была передача с параметром )


 
Eraser ©   (2005-08-15 21:13) [4]

ksa2002   (15.08.05 19:17) [3]

Как вариант можно использовать сообщения - 2 параметра есть как-никак.


 
ksa2002   (2005-08-15 22:36) [5]

Возникла проблема !
При создание крит секции вылетает ошибка
 private
 FCSBuf1 : TCriticalSection;
.................
 FCSBuf1.Create;

EAccessViolation  ...."ntdll.dll"

хелп ми!


 
Eraser ©   (2005-08-15 22:42) [6]

Не создан объект!
___
Я бы использовал RTL_CRITICAL_SECTION и ф-ии InitializeCriticalSection, EnterCriticalSection, LeaveCriticalSection.


 
Наиль ©   (2005-08-15 22:46) [7]

>[5]
Кто же так создаёт объекты ?!
Смотри как надо!
FCSBuf1:=TCriticalSection.Create;


 
ksa2002   (2005-08-15 23:25) [8]

ещё вопрос
два разных потока присваевают значение одной переменной
как приостоновить один потока пока не будет произведена обработка  значения? (если можно с примером)


 
Eraser ©   (2005-08-15 23:28) [9]

ksa2002   (15.08.05 23:25) [8]

Именно для этого и созданы критические секции!


 
ksa2002   (2005-08-15 23:34) [10]

про обработку понятно
я имел ввиду что есть паблик переменная которой присваевается значение перед вызовом крит секции, но присваение не входит в крит секцию ..как в этом случаи быть? (ведь данную переменую можно затереть)


 
Alexander Panov ©   (2005-08-15 23:37) [11]

Может быть попробуешь по форуму поискать?
За минуту поиска находится вот такая ветка
http://delphimaster.net/view/1-1123147749/


 
Eraser ©   (2005-08-15 23:39) [12]

ksa2002   (15.08.05 23:34) [10]

Тогда никак! Если эта переменная не пренадлежит экземпляру наследника TThread данного потока. Если это так, то защищать ничего не надо.
Так же можно не защищать любые однобайтовые переменые.


 
ksa2002   (2005-08-15 23:46) [13]

т.е. если так
в главном потоке
public
str:string
----------------------------
поток  1-й
str:=знач1;
Synchronize(f_main);

поток  2-й
str:=знач2;
Synchronize(f_main);
---------------------------
получается  что мне не надо защищать str?(в момент присвоения)


 
Eraser ©   (2005-08-15 23:48) [14]

ksa2002   (15.08.05 23:46) [13]

Надо!
Т.к. str - глобальная переменная! Повторюсь - защищать не надо только переменные (поля) экземпляра текущего потока.


 
DrPass ©   (2005-08-15 23:50) [15]

Надо. И не только в момент присвоения, поэтому самый разумный способ - перенести это присвоение в функцию f_main


 
ksa2002   (2005-08-15 23:50) [16]

вот я о том же , но как ? Есть симофоры но у меня нет примера по их использованию


 
ksa2002   (2005-08-15 23:52) [17]


> DrPass ©  

можно...т.е. это присвоение для каждой переменной, а если у меня автомат. создание потоков? но есть же другой способ


 
Alexander Panov ©   (2005-08-15 23:53) [18]

Ты пойми, защищаются, по-существу, не сами переменные, а код, который эти переменные использует.


 
Alexander Panov ©   (2005-08-15 23:57) [19]

Блин, не сидел бы сейчас за покетом, привел бы пару примеров. А вообще, примеров море, как здесь, таки в интернете. Кроме того, на сайте есть статьи по потокам.


 
DrPass ©   (2005-08-16 00:03) [20]


> ksa2002   (15.08.05 23:52) [17]

Заведи локальное для потока поле с нужным значением, и устанавливай его персонально для каждого экземпляра TThread. А присвоение значения этого поля глобальной переменной вынеси в синхронизируемый код. В противном случае накладки возможны даже в случае, когда...
str:=знач1;
<в этот момент второй поток меняет значение str>
Synchronize(f_main);


 
Eraser ©   (2005-08-16 00:13) [21]

ksa2002

EnterCriticalSection(lpCrtlSctn);
str:=знач1;
Synchronize(f_main);
LeaveCriticalSection(lpCrtlSctn);


При загрузке приложения выполни InitializeCriticalSection(lpCrtlSctn);


 
Defunct ©   (2005-08-16 03:05) [22]

ksa2002   (15.08.05 23:46) [13]
> получается  что мне не надо защищать str?(в момент присвоения)
Eraser ©   (15.08.05 23:48) [14]
> Надо!

В общем-то защищать надо, только в данном конкретном случае это ничего не даст. Т.е. если речь идет о выводе переменной на экран можем наблюдать
1
1

или
2
2

вместо
1
2

> ksa2002   (15.08.05 23:50) [16]
CriticalSection и семафоры тут не нужны, Synchronize работает по механизму "рандеву" между любым потоком и основным.

Вам нужно передавать именно переменную. Учитывая, что внутри Synchronize любой код становится потокобезопасным, т.к. исполнятся строго в основном потоке, самым лучшим выходом может быть такой:

// рисуем какую-то дополнительную процедуру, которую будем
// синхронизировать с осн. потоком.
procedure TMyThread.SyncProc;
begin
 // в ней вызываем все, что надо и с любыми параметрами.
 // здесь же можем безопастно менять любые глобальные переменные.
 // здесь же мы можем и обращаться к VCL
 f_main( 2 );
end;

procedure TMyThread.Execute;
begin
 ...
 Synchronize( SyncProc );
 ...
end;


 
ksa2002   (2005-08-16 12:11) [23]

хм.... а ведь правда ....спасибо проверю :)


 
ksa2002   (2005-08-16 16:51) [24]


> // рисуем какую-то дополнительную процедуру, которую будем
> // синхронизировать с осн. потоком.
> procedure TMyThread.SyncProc;
> begin
>  // в ней вызываем все, что надо и с любыми параметрами.
>  // здесь же можем безопастно менять любые глобальные переменные.
>
>  // здесь же мы можем и обращаться к VCL
>  f_main( 2 );
> end;
>
> procedure TMyThread.Execute;
> begin
>  ...
>  Synchronize( SyncProc );
>  ...
> end;


Возникла следующая ошибка при вызове Synchronize( SyncProc );

There is no overloaded version of "Synchronize" that can be called with these arguments


 
ksa2002   (2005-08-16 16:56) [25]

походу TMyThread.SyncProc должна располагатся в основном потоке, не хотелось бы. Хотелось бы  всё проворачивать в текущем потоке.


 
Alexander Panov ©   (2005-08-16 17:03) [26]

Ты бы почитал все-таки книжки, статьи и пр.

uses ...,
  Unit1;

TMyThread=class(TThread)
private
  FId: String;
  FCounter: Integer;
  procedure DoPrint;
protected
  procedure Execute; override;  
public
  constructor Create(const aId: String);
end;

...

constructor TMyThread.Create(const aId: String);
begin
  inherited Create(True);
  FreeOnTerminate := True;
  FId := Id;
  FCounter := 0;
  Resume;
end;

procedure Execute;
begin
  while not Terminated do
  begin
     Sleep(1);
     if Terminated then Break;
     Inc(FCounter);
     Synchronize(DoPrint);
  end;
end;

procedure DoPrint;
begin
  Form1.Label1.Caption := FId+":"+IntToStr(Counter);
end;


 
Eraser ©   (2005-08-16 17:03) [27]

ksa2002   (16.08.05 16:56) [25]

Абсолютно не важно где объявлена и реализована SyncProc. Главное чтобы это был процедурный метод без параметров.


 
Alexander Panov ©   (2005-08-16 17:04) [28]

В предыдущем посте читать:
вместо procedure Execute; procedure TMyThread.Execute;
вместо procedure DoPrint; procedure TMyThread.DoPrint;


 
ksa2002   (2005-08-16 17:25) [29]


> Alexander Panov ©   (16.08.05 17:03) [26]

Спасибо за помощь , но вроде форум для этого и предназначен.
Информация мало. В книгах почти не описан, в инете только куски кода.Поэтому я и пытаюсь уяснить принцип работы данных вещей.


 
Alexander Panov ©   (2005-08-16 17:38) [30]

На этом сайте есть много занимательных и полезных статей не только о потоках.
О потоках вот эта:
http://www.delphimaster.ru/articles/panov/index.html


 
han_malign ©   (2005-08-16 17:57) [31]

>Eraser ©   (16.08.05 00:13) [21]
>.............................
>EnterCriticalSection(lpCrtlSctn);
>str:=знач1;
>Synchronize(f_main);
>LeaveCriticalSection(lpCrtlSctn);
- грубое(не сказать тупое) решение - теперь в f_main вызываем функцию потока защищенную той-же критической секцией, получаем deadlock, и долго-долго ищем почему программы зависает...

если так уж хочется синхронный метод с параметрами(см. DrPass ©(16.08.05 00:03)[20]):

type TSyncMethod = procedure(Param1: TType1;...;ParamN: TTypeN; var AResult: TTypeRes);
..............................
private
   FParam1: TType1;
..............................
   FParamN: TTypeN;
   FResult: TTypeRes;
   function SyncMethod(Param1: TType1;...;ParamN: TTypeN): AResult;
   procedure _SyncMethod;
public
   OnSyncMethod: TSyncMethod;
..............................
function TSMThread.SyncMethod(Param1: TType1;...;ParamN: TTypeN): TTypeRes;
begin
  FParam1:= Param1;
  ................
  FParamN:= ParamN;
  Syncronise(_SyncMethod);
  Result:= FResult;
end;

procedure TSMThread._SyncMethod;
begin
  if(Assigned(OnSyncMethod)) then OnSyncMethod(FParam1,...,FParamN,FResult);
end;



Страницы: 1 вся ветка

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

Наверх




Память: 0.55 MB
Время: 0.039 c
11-1106815076
Неуловимый Джо
2005-01-27 11:37
2005.09.11
strlist в ListBox


14-1124348891
vidiv
2005-08-18 11:08
2005.09.11
Самая популярная в мире игра!


3-1122533289
ChI
2005-07-28 10:48
2005.09.11
поиск по индексным полям вTDBF


3-1122898658
td
2005-08-01 16:17
2005.09.11
как можно посмотреть запрос Оракл?


14-1124116765
Kerk
2005-08-15 18:39
2005.09.11
Чем-то письмо в "молодежный журнал" напоминает :)))