Форум: "Начинающим";
Текущий архив: 2008.09.07;
Скачать: [xml.tar.bz2];
ВнизДоступ к данным с разных потоков Найти похожие ветки
← →
Ruzzz © (2008-07-25 03:33) [0]Как организовать доступ к данным с разных потоков в одном приложении?
Как безопасно считывать значения переменных, хранящих настройки, из разных потоков?
Я считаю: к любому параметру настроек доступ на чтение/запись только внутри CriticalSection, но в таком случае как это сделать удобней? Ведь настроек много. Может создавать хеш, и создать две функции: read/write(Name, Value), внутри которых и будет EnterCriticalSection...LeaveCriticalSection ? но это как-то не удобно. Может есть другие способы?
Если использовать класс для хранения настроек, то как используя EnterCriticalSection...LeaveCriticalSection, получать доступ read/write к его полям? что-то не пойму и все :( я так понимаю, использовать EnterCriticalSection...LeaveCriticalSection внутри методов такого класса это уже ошибка, т.к. ссылаться на сам обьект нужно внутри EnterCriticalSection...LeaveCriticalSection, или не так?
← →
Loginov Dmitry © (2008-07-25 08:00) [1]> Как безопасно считывать значения переменных, хранящих настройки,
> из разных потоков?
Считывание безопасно, если не выполняется одновременной записи.
> Я считаю: к любому параметру настроек доступ на чтение/запись
> только внутри CriticalSection, но в таком случае как это
> сделать удобней? Ведь настроек много. Может создавать хеш,
> и создать две функции: read/write(Name, Value), внутри
> которых и будет EnterCriticalSection...LeaveCriticalSection
> ? но это как-то не удобно. Может есть другие способы?
Разработай отдельный класс для доступа к настройкам приложения. Добавь в секцию public методы Lock() и Unlock(), это позволит обеспечить целостность обращения сразу к группе настроек. В каждом методе чтения/записи настроек используй следующий шаблон:Lock;
try
// обращение к настройкам
finally
UnLock;
end;
← →
Сергей М. © (2008-07-25 09:37) [2]
> использовать EnterCriticalSection...LeaveCriticalSection
> внутри методов такого класса это уже ошибка
Настолько же ошибка, насколько и использование любых других API-функций)
← →
han_malign © (2008-07-25 10:46) [3]
> т.к. ссылаться на сам обьект нужно внутри EnterCriticalSection...LeaveCriticalSection, или не так?
- а что - порядок создания и время жизни тебе(разработчику) не известно?
Объект просто должен создаваться в основном потоке до запуска доп. потоков и разрушаться после остановки всех доп. потоков... Короче - иметь гарнтированное время жизни в области водимости.
← →
Leonid Troyanovsky © (2008-07-25 11:01) [4]
> Ruzzz © (25.07.08 03:33)
> Если использовать класс для хранения настроек, то как используя
> EnterCriticalSection...LeaveCriticalSection, получать доступ
> read/write к его полям? что-то не пойму и все :(
Доступ к полям надо осуществлять через геттер/сеттер,
т.е., потоки должны оперировать нужным свойством (property).
Ну, а EnterCriticalSection...LeaveCriticalSection обрамляет
код метода доступа (read & write).
И не забудь в конструкторе инициализировать КС.
--
Regards, LVT.
← →
Тын-Дын © (2008-07-25 11:30) [5]
> Ruzzz © (25.07.08 03:33)
> Как организовать доступ к данным с разных потоков в одном
> приложении?
>
> Как безопасно считывать значения переменных, хранящих настройки,
> из разных потоков?
>
> Я считаю: к любому параметру настроек доступ на чтение/запись
> только внутри CriticalSection, но в таком случае как это
> сделать удобней? Ведь настроек много. Может создавать хеш,
> и создать две функции: read/write(Name, Value), внутри
> которых и будет EnterCriticalSection...LeaveCriticalSection
> ? но это как-то не удобно. Может есть другие способы?
>
> Если использовать класс для хранения настроек, то как используя
> EnterCriticalSection...LeaveCriticalSection, получать доступ
> read/write к его полям? что-то не пойму и все :( я так понимаю,
> использовать EnterCriticalSection...LeaveCriticalSection
> внутри методов такого класса это уже ошибка, т.к. ссылаться
> на сам обьект нужно внутри EnterCriticalSection...LeaveCriticalSection,
> или не так?
Всё просто.
TOptionClass=class
private
FCS: RTL_CRITICAL_SECTION;
FOptionList: TStringList;
function GetValue(Index: String): String;
procedure SetValue(Index: String; const Value: String);
procedure Lock;
procedure Unlock;
public
constructor Create;
destructor Destroy; override;
// procedure Save(const FilePath: String);
// procedure Load(const FilePath: String);
property Value[Index: String]: String read GetValue write SetValue;
end;
TForm1 = class(TForm)
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
{ TOptionClass }
constructor TOptionClass.Create;
begin
inherited;
InitializeCriticalSection(FCS);
FOptionList := TStringList.Create;
end;
destructor TOptionClass.Destroy;
begin
FOptionList.Free;
DeleteCriticalSection(FCS);
inherited;
end;
function TOptionClass.GetValue(Index: String): String;
begin
Lock;
try
Result := FOptionList.Values[Index];
finally
Unlock;
end;
end;
procedure TOptionClass.SetValue(Index: String; const Value: String);
begin
Lock;
try
FOptionList.Values[Index] := Value;
finally
Unlock;
end;
end;
procedure TOptionClass.Lock;
begin
EnterCriticalSection(FCS);
end;
procedure TOptionClass.Unlock;
begin
LeaveCriticalSection(FCS);
end;
← →
Ruzzz © (2008-07-25 17:14) [6]Спасибо!!! Тын-Дын за код :) только вот решил TStringList не использовать, а делать set/get для каждого параметра отдельно, так как разные типы есть и не охота каждый раз из строки/в строку переводить, плюс добавлю проверку на правильность.
у меня еще вопросик, даже три :)
1) Как-то не понятно, получается что к отдельному потоку (к его адресному пространству) относится только, то что внутри метода Execute? то есть сам обьект-наследник TThread принадлежит главному потоку, тогда получается что поток в методе Execute не может безопасно изменять свои property?
2) Нормально ли будет использовать raise внутри EnterCriticalSection...LeaveCriticalSection, т.е. я пишу код записи, поэтому он внутри EnterCriticalSection...LeaveCriticalSection, но сперва я должен проверить, валидное ли новое значение, или просто проверять до входа в CriticalSection? Глупый наверное вопрос :) ну уж извините, но наверное нужно будет читать API чтоб знать больше о разных CriticalSection
3) Loginov Dmitry вам спасибо за "Считывание безопасно, если не выполняется одновременной записи." - как-то аж яснее стало! но это точно? :) т.е. если одновременно несколько потоков считывают какую-то ячейку памяти, то это безопасно и если такой код не включать в CriticalSection - это считается нормальным тоном в программировании?
← →
Тын-Дын © (2008-07-25 17:32) [7]
> Спасибо!!! Тын-Дын за код :) только вот решил TStringList
> не использовать, а делать set/get для каждого параметра
> отдельно, так как разные типы есть и не охота каждый раз
> из строки/в строку переводить, плюс добавлю проверку на
> правильность.
Это разовое решение, конечно.
Мне кажется, что лучше будет написать прослойку между классом хранения данных и основной программой для преобразования данных.
В конце-концов, можно и тип поля внести в класс для универсальности ввести.
> 1) Как-то не понятно, получается что к отдельному потоку
> (к его адресному пространству) относится только, то что
> внутри метода Execute? то есть сам обьект-наследник TThread
> принадлежит главному потоку, тогда получается что поток
> в методе Execute не может безопасно изменять свои property?
>
Адресное пространство для всех потоков одно. Другое дело, что обращаться из разных потоков к переменным, где бы они не были созданы, надо потокобезопасно.
Поток может обращаться к любым ресурсам безопасно при условии, что он делает это единолично.
> 2) Нормально ли будет использовать raise внутри EnterCriticalSection.
> ..LeaveCriticalSection, т.е. я пишу код записи, поэтому
> он внутри EnterCriticalSection...LeaveCriticalSection, но
> сперва я должен проверить, валидное ли новое значение, или
> просто проверять до входа в CriticalSection? Глупый наверное
> вопрос :) ну уж извините, но наверное нужно будет читать
> API чтоб знать больше о разных CriticalSection
raise внутри потока использовать вполне нормально. Только исключение погаснет в недрах потока, повалив его, если не применить дополнительных усилий для обработки исключения.
> 3) Loginov Dmitry вам спасибо за "Считывание безопасно,
> если не выполняется одновременной записи." - как-то аж яснее
> стало! но это точно? :) т.е. если одновременно несколько
> потоков считывают какую-то ячейку памяти, то это безопасно
> и если такой код не включать в CriticalSection - это считается
> нормальным тоном в программировании?
Это точно-)
но ведь возможно, что когда-либо потребуется повторное использование кода? В этом случае нужн обыть уверенным, что другие потоки не попытаются записывать в общие области памяти.
← →
Loginov Dmitry © (2008-07-25 22:00) [8]> Нормально ли будет использовать raise внутри EnterCriticalSection...Leave
> CriticalSectionEnterCriticalSection(...);
try
finally
LeaveCriticalSection(...);
end;
в этом случае raise внутри блока try..finally вызывать вполне можно. LeaveCriticalSection(...) сработает, не сомневайся! :)
> т.е. если одновременно несколько потоков считывают какую-
> то ячейку памяти, то это безопасно и если такой код не включать
> в CriticalSection
Насчет ячейки памяти - нормально. Однако при обращении к тем или иным из нескольких потоков нужно знать, является ли это безопасным. По всякому бывает.
> это считается нормальным тоном в программировании?
обычно где есть чтение, там есть и запись. Если записи нет, то обычно - является нормальным тоном.
← →
Loginov Dmitry © (2008-07-25 22:01) [9]> к тем или иным объектам
← →
Сергей М. © (2008-07-26 01:24) [10]
> к отдельному потоку (к его адресному пространству)
Нет у потока своего адресного пространства.
TLS (thread local storage) пока не в счет - оно тебя сейчас никак не парит.
> обьект-наследник TThread принадлежит главному потоку
Делфи-объект не может принадлежать никакому потоку.
Он просто есть или его нет, вне зависимости от того, кто его вызвал к жизни кто явился его убийцей)
← →
Сергей М. © (2008-07-26 01:26) [11]
> поток в методе Execute не может безопасно изменять свои
> property?
свои - на здоровье.
Страницы: 1 вся ветка
Форум: "Начинающим";
Текущий архив: 2008.09.07;
Скачать: [xml.tar.bz2];
Память: 0.5 MB
Время: 0.005 c