Использование критических секций
От: AMogil Россия  
Дата: 25.09.04 18:27
Оценка:
Здравствуйте.

Хотелось бы уточнить. Существует следующий класс, использующий дополнительную нить. Из этой нити необходимо вызывать метод данного класса:

Класс:

TMainClass = class(TInterfacedObject)
private
  FCommandText: WideString;
  FCriticalSection: TCriticalSection;
  FThreadClass: TThreadClass;
public
  constructor Create; virtual;
  destructor Destroy; override;

  function GetCommandText: WideString; overload;
  procedure SetCommandText(const Value: WideString);
end;
    
...
    
constructor TMainClass.Create;
begin
  inherited;
  FCriticalSection := TCriticalSection.Create;
  FThreadClass := TThreadClass.Create(Self);
  SetSQLCommandText('ddd');
  FThreadClass.Resume;    
end;
    
function TMainClass.GetCommandText: WideString;
begin
  FCriticalSection.Enter;
  try
    Result := FCommandText;
  finally
    FCriticalSection.Leave;
  end;
end;

procedure TMainClass.SetCommandText(const Value: WideString);
begin
  FCriticalSection.Enter;
  try
    FCommandText := Value;
  finally
    FCriticalSection.Leave;
  end;
end;

Нить:
    
TThreadClass = class(TThread)
protected
  FOwner: TObject;
  procedure Execute; override;
public
  constructor Create(Owner: TObject); virtual;
  destructor Destroy; override;
end;
    
...
    
constructor TThreadClass.Create(Owner: TObject);
begin
  inherited Create(True);
  FOwner := Owner;
  FreeOnTerminate := False;
end;
    
procedure TDatabaseConnectionThread.Execute;
var
  S: WideString;
begin
  S := TMainClass(FOwner).GetCommandText;
  ...
end;



Суть вопроса: корректно ли такое использование критической секции? Просто справка Delphi говорит, что

Critical sections must be global in scope so that they are available to all threads


Но в данном случае нить не видит объект критической секции.

Алексей.
Re: Использование критических секций
От: Artem Dudkin Россия  
Дата: 25.09.04 19:51
Оценка:
AM>Суть вопроса: корректно ли такое использование критической секции?

Тебя интересует чисто теоретический ответ?
Или чисто практический?

Чисто практический ответ тебе даст тест. Который я за тебя писать не буду
А чисто теоретический можно получить, просмотрев сорсы. Которые тоже никто кроме тебя...
Re: Использование критических секций
От: gribunin Россия  
Дата: 25.09.04 21:13
Оценка: 2 (1)
Здравствуйте, AMogil, Вы писали:

AM>

AM>Critical sections must be global in scope so that they are available to all threads


AM>Но в данном случае нить не видит объект критической секции.


TCriticalSection просто обёртка над функциями API, которым наплевать на то в каком scope что находится. В вашем случае всё должно быть нормально.
----------------
Кирилл Грибунин
Re: Использование критических секций
От: Silentor Украина  
Дата: 25.09.04 21:27
Оценка:
Прочитал я твои 12618 байт текста и 26 сентября в 00:25 решил ответить...
Приветствую, AMogil!


A> procedure TDatabaseConnectionThread.Execute;

A> var
A> S: WideString;
A> begin
Вот здесь надо войти в ту же крит. секцию
A> S := TMainClass(FOwner).GetCommandText;
А где-то здесь, соответственно, выйти
A> ...
A> end;

A> Суть вопроса: корректно ли такое использование критической секции?

A> Просто справка Delphi говорит, что

A> Critical sections must be global in scope so that they are available to
A> all threads

Всё правильно, они должны пользоваться методами одного объекта крит. секции, тогда он сможет их разруливать.

A> Но в данном случае нить не видит объект критической секции.

А зря

-- Вишаю преразбестнейшие регарды, Silentor.
...Cantrip "pinch" the barmaid's rear as she walks by the fighter.
Posted via RSDN NNTP Server 1.9 gamma
Re[2]: Использование критических секций
От: Silentor Украина  
Дата: 25.09.04 21:35
Оценка:
Прочитал я твои 9173 байт текста и 26 сентября в 00:37 решил ответить...
Приветствую, Silentor!

A>> procedure TDatabaseConnectionThread.Execute;

A>> var
A>> S: WideString;
A>> begin
S> Вот здесь надо войти в ту же крит. секцию
A>> S := TMainClass(FOwner).GetCommandText;
S> А где-то здесь, соответственно, выйти
A>> ...
A>> end;
Сорри, сглупил. Больше не буду. Конечно в GetCommandText уже осуществляется вход в крит. секцию.

-- Вишаю преразбестнейшие регарды, Silentor.
...[AthlonXP 1600+ | 384 Mb | GeForceMX400 32Mb | 20 Gb | DVD 16x/48x | WinXP Pro SP1]
Posted via RSDN NNTP Server 1.9 gamma
Re: Использование критических секций
От: akasoft Россия  
Дата: 26.09.04 07:32
Оценка:
Здравствуйте, AMogil, Вы писали:

AM>
    
AM>procedure TDatabaseConnectionThread.Execute;
AM>var
AM>  S: WideString;
AM>begin
AM>  S := TMainClass(FOwner).GetCommandText;
AM>  ...
AM>end;
    
AM>



Эко загнуто. Выглядит немного не естественно. Потому что, что мешало в критическую секцию обрамить вызов GetCommandText... И вообще, что с чем конкурирует? Дополнительный поток с главным? А помним про то, что из доп. потоков к VCL надо бы обращаться с помошью Synchronize() ? Похоже, не помним, иначе бы написал по другому..

AM>Суть вопроса: корректно ли такое использование критической секции?


То как написано? Ну а почему нет.

Конкретно в приведённой цитате мне думается, что имеется ввиду, что если ты непосредственно хочешь поставить вызов Enter/Leave в методе потока, то секция должна быть её доступна (видна). Но ты же метод класса вызываешь, а в его теле секция видна.
... << RSDN@Home 1.1.4 beta 3 rev. 189 Тишь да гладь, да Божья благодать >>
Re[2]: Использование критических секций
От: AMogil Россия  
Дата: 26.09.04 07:57
Оценка:
Здравствуйте, akasoft, Вы писали:


A>Эко загнуто. Выглядит немного не естественно. Потому что, что мешало в критическую секцию обрамить вызов GetCommandText...

Для этого прищлось бы расширить область видимости объекта-критической секции, что по-моему лишнее.

A>И вообще, что с чем конкурирует? Дополнительный поток с главным?

В данном случае — да.
A>А помним про то, что из доп. потоков к VCL надо бы обращаться с помошью Synchronize() ? Похоже, не помним, иначе бы написал по другому..
Synchronize не хочется использовать, т.к. возможно в будущем придется выносить TMainClass также в отдельный поток. Хотелось бы сразу написать код, который был корректен для обоих случаев, поэтому Synchronize и не используется.

Алексей.
Re[3]: Использование критических секций
От: AMogil Россия  
Дата: 26.09.04 08:07
Оценка:
Здравствуйте, AMogil, Вы писали:

AM>Synchronize не хочется использовать, т.к. возможно в будущем придется выносить TMainClass также в отдельный поток. Хотелось бы сразу написать код, который был корректен для обоих случаев, поэтому Synchronize и не используется.


Кроме того, Synchronize принимает метод без параметров. Здесь же вызывается функция.

Алексей.
Re[2]: Использование критических секций
От: gribunin Россия  
Дата: 26.09.04 08:42
Оценка:
Здравствуйте, akasoft, Вы писали:

> А помним про то, что из доп. потоков к VCL надо бы обращаться с помошью Synchronize() ? Похоже, не

> помним, иначе бы написал по другому..

В приведённом примере дополнительный поток не обращается к методам VCL, поэтому выполнять его действия в основном потоке (через Synchronize) нет никакой необходимости.
----------------
Кирилл Грибунин
Re[3]: Использование критических секций
От: AMogil Россия  
Дата: 26.09.04 08:46
Оценка:
Здравствуйте, gribunin, Вы писали:

G>Здравствуйте, akasoft, Вы писали:


>> А помним про то, что из доп. потоков к VCL надо бы обращаться с помошью Synchronize() ? Похоже, не

>> помним, иначе бы написал по другому..

G>В приведённом примере дополнительный поток не обращается к методам VCL, поэтому выполнять его действия в основном потоке (через Synchronize) нет никакой необходимости.


Позвольте возразить словами Borland'a:

Delphi syntax:

procedure Synchronize(Method: TThreadMethod);

C++ syntax:

void __fastcall Synchronize(TThreadMethod &Method);

Description

Synchronize causes the call specified by Method to be executed using the main thread, thereby avoiding multi-thread conflicts. If you are unsure whether a method call is thread-safe, call it from within the Synchronize method to ensure that it executes in the main thread.

Execution of the thread current is suspended while Method executes in the main thread.

Warning: Do not call Synchronize from within the main thread. This can cause an infinite loop.

Note: You can also protect unsafe methods using critical sections or the multi-read exclusive-write synchronizer.


Про VCL не слова.

Алексей.
Re[3]: Использование критических секций
От: akasoft Россия  
Дата: 26.09.04 16:21
Оценка: 2 (1)
Здравствуйте, AMogil, Вы писали:

AM>В данном случае — да.


Что ж, на мой взгляд тогда всё корректно.

AM>Synchronize не хочется использовать, т.к. возможно в будущем придется выносить TMainClass также в отдельный поток.


Э-э-э, торможу что-то

Выносить — имеется ввиду поле этого класса сделать членом класса потока?
... << RSDN@Home 1.1.4 beta 3 rev. 189 Тишь да гладь, да Божья благодать >>
Re[4]: Использование критических секций
От: gribunin Россия  
Дата: 26.09.04 16:21
Оценка:
Здравствуйте, AMogil, Вы писали:

AM>Про VCL не слова.


И что? Метод Synchronize выполняет переданную ему процедуру в основном потоке. Борланд порекомендовал тем, кто не уверен, что его код thread-safe, тоже на всякий случай вызывать его в основном потоке. В частности, почти все VCL методы не thread-safe. Но в данном случае всё написано корректно и никакой необходимости использовать Synchronize нет.
----------------
Кирилл Грибунин
Re[4]: Использование критических секций
От: AMogil Россия  
Дата: 27.09.04 03:59
Оценка:
Здравствуйте, akasoft, Вы писали:

A>Здравствуйте, AMogil, Вы писали:


AM>>В данном случае — да.


A>Что ж, на мой взгляд тогда всё корректно.


AM>>Synchronize не хочется использовать, т.к. возможно в будущем придется выносить TMainClass также в отдельный поток.


A>Э-э-э, торможу что-то


A>Выносить — имеется ввиду поле этого класса сделать членом класса потока?


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

Алексей.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.