Модераторы: Poseidon, Snowy, bems, MetalFan
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> TStringList и многопоточность, Были ли у кого проблемы ? 
:(
    Опции темы
Gershkovich
Дата 1.4.2008, 12:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 243
Регистрация: 8.2.2006

Репутация: 0
Всего: 2



Всем привет!

У меня многопоточное приложение.
Для взаимодействия потоков использую синхронизированный буфер.
Обыкновенная синхронизация TStringList через критическую секцию:
Код

type
  TSyncStringList = class

    constructor Create;
    destructor Destroy; override;

    procedure Push(LogString : string);
    procedure Pop(var LogString : string);

    procedure FillTo(Strings : TStrings);

  protected
    List : TStringList;

  private
    CS : TCriticalSection;
  end;

  EmptyListException = class(Exception)
  end;

  
implementation


constructor TSyncStringList.Create;
begin

  inherited Create;

  List:= TStringList.Create;
  CS:= TCriticalSection.Create;
end;


destructor TSyncStringList.Destroy;
begin

  CS.Free;
  List.Free;

  inherited Destroy;
end;


procedure TSyncStringList.Push(LogString : string);
begin
  CS.Enter;
  List.Add(LogString);
  CS.Leave;
end;


procedure TSyncStringList.Pop(var LogString : string);
begin

  CS.Enter;

  try

    if List.Count < 1 then begin
      raise EmptyListException.Create('List is empty');
    end;

    LogString:= List[0];
    List.Delete(0);
    
  finally
    CS.Leave;
  end;
end;


procedure TSyncStringList.FillTo(Strings : TStrings);
begin
  CS.Enter;
  Strings.AddStrings(List);
  CS.Leave;
end;



Условия выполнения такие: одновременно  используют этот буфер около 10 потоков
и еще главный поток использует FillTo для отображения строк в Memo

Периодически возникает access violation
Причем совершенно непредсказуемо и бессистемно. По разным адресам и с разным кодом ошибки.
Отловить очень трудно - у меня не получилось.
Частенько  падает в методе FillTo на строке CS.Enter;
Иногда вываливается в дебагер и останавливается на функции LoadAsRes

Были ли у кого такие проблемы ? Где грабли ?
Стоит ли перейти на использование другой схемы (например record + TList) ?


Заранее спасибо.

PM MAIL   Вверх
Rennigth
Дата 1.4.2008, 13:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Участник Клуба
Сообщений: 1708
Регистрация: 21.6.2004
Где: Moscow

Репутация: 49
Всего: 76



Gershkovich, Первое, как ты обращаешься к самому экземпляру TSyncStringList? Он ведь иоже должен быть защищен...
Второе
Цитата(Gershkovich @  1.4.2008,  12:32 Найти цитируемый пост)
и еще главный поток использует FillTo для отображения строк в Memo

Выполняешь ли ты этот метод в Synchronize?

Добавлено через 4 минуты и 25 секунд
Gershkovich, ну и еще, существует такая штука как TThreadList, и не надо изобретать велосипеды smile


--------------------
(* Honesta mors turpi vita potior *)
PM MAIL ICQ   Вверх
Gershkovich
Дата 1.4.2008, 13:26 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 243
Регистрация: 8.2.2006

Репутация: 0
Всего: 2



Rennigth, 
1. А как он должен быть защищен ?
Я, честно говоря, ничего такого не делал...
Создаю один экземпляр TSyncStringList и передаю его в конструкторы потоков.
И все. Должно еще что то быть ? 

2. Извини. Под словами "главный поток" я имел в виду "VCL поток". 
Т.е.  Synchronize  не нужен.

PM MAIL   Вверх
MetalFan
Дата 1.4.2008, 13:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Аццкий Сотона
****


Профиль
Группа: Комодератор
Сообщений: 3815
Регистрация: 2.10.2006
Где: Moscow

Репутация: 62
Всего: 128



каждый Enter-Leave желательно в try..finally "облачить"...
а в общем вроде криминала не вижу. возможно ошибка в другом месте



--------------------
There are always someone smarter than you...
PM MAIL   Вверх
Rennigth
Дата 1.4.2008, 13:54 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Участник Клуба
Сообщений: 1708
Регистрация: 21.6.2004
Где: Moscow

Репутация: 49
Всего: 76



Gershkovich, хм, вообще странно, попробовал твой код на тестовом приложении, все в порядке..., работает без ошибок.
Код

unit Unit30;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, SyncObjs, StdCtrls, Contnrs;

type
  TSyncStringList = class

    constructor Create;
    destructor Destroy; override;

    procedure Push(LogString : string);
    procedure Pop(var LogString : string);

    procedure FillTo(Strings : TStrings);

  protected
    List : TStringList;

  private
    CS : TCriticalSection;
  end;

  EmptyListException = class(Exception)
  end;

  TSomeThread = class(TThread)
  private
    FBuf: TSyncStringList;
  protected
    procedure Execute; override;
  public
    constructor Create(ABuf: TSyncStringList); reintroduce; virtual;
  end;


  TForm30 = class(TForm)
    btn1: TButton;
    mmo1: TMemo;
    btn2: TButton;
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
    procedure btn1Click(Sender: TObject);
    procedure btn2Click(Sender: TObject);
  private
    FThreads: TObjectList;
    FSyncStringList: TSyncStringList;
  end;

var
  Form30: TForm30;

implementation

{$R *.dfm}

constructor TSyncStringList.Create;
begin

  inherited Create;

  List:= TStringList.Create;
  CS:= TCriticalSection.Create;
end;


destructor TSyncStringList.Destroy;
begin

  CS.Free;
  List.Free;

  inherited Destroy;
end;


procedure TSyncStringList.Push(LogString : string);
begin
  CS.Enter;
  List.Add(LogString);
  CS.Leave;
end;


procedure TSyncStringList.Pop(var LogString : string);
begin

  CS.Enter;

  try

    if List.Count < 1 then begin
      raise EmptyListException.Create('List is empty');
    end;

    LogString:= List[0];
    List.Delete(0);

  finally
    CS.Leave;
  end;
end;


procedure TSyncStringList.FillTo(Strings : TStrings);
begin
  CS.Enter;
  Strings.AddStrings(List);
  CS.Leave;
end;

procedure TForm30.btn1Click(Sender: TObject);
begin
  FSyncStringList.FillTo(mmo1.Lines);
end;

procedure TForm30.btn2Click(Sender: TObject);
var
  lSomeThread: TSomeThread;
  i: Integer;
begin
  for i := 0 to 99 do
  begin
    lSomeThread := TSomeThread.Create(FSyncStringList);
    lSomeThread.Resume;
    FThreads.Add(lSomeThread);
  end;
end;

procedure TForm30.FormCreate(Sender: TObject);
begin
  FSyncStringList := TSyncStringList.Create;
  FThreads := TObjectList.Create;
end;

{ FSomeThread }

constructor TSomeThread.Create(ABuf: TSyncStringList);
begin
  inherited Create(True);
//  FreeOnTerminate := True;
  FBuf := ABuf;
end;

procedure TSomeThread.Execute;
var
  lStr: string;
begin
  inherited;
  while not Terminated do
  begin
    sleep(50);
    FBuf.Push('Push: ' + IntToStr(Handle));
    sleep(50);
    FBuf.Pop(lStr);
  end;
end;

procedure TForm30.FormDestroy(Sender: TObject);
var
  i: Integer;
begin
  for i := 0 to FThreads.Count - 1 do
    TSomeThread(FThreads.Items[i]).Terminate;
  FThreads.Free;
  FSyncStringList.Free;
end;

end.




--------------------
(* Honesta mors turpi vita potior *)
PM MAIL ICQ   Вверх
Alexeis
Дата 1.4.2008, 14:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Амеба
Group Icon


Профиль
Группа: Админ
Сообщений: 11743
Регистрация: 12.10.2005
Где: Зеленоград

Репутация: 109
Всего: 459



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


--------------------
Vit вечная память.

Обсуждение действий администрации форума производятся только в этом форуме

гениальность идеи состоит в том, что ее невозможно придумать
PM ICQ Skype   Вверх
Gershkovich
Дата 1.4.2008, 14:37 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 243
Регистрация: 8.2.2006

Репутация: 0
Всего: 2



Ну что ж...
спасибо за участие
наверно я где то напортачил
буду разбираться...

Всем спасибо.
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Delphi: Общие вопросы"
SnowyMetalFan
bemsPoseidon
Rrader

Запрещается!

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делиться вскрытыми компонентами

  • Литературу по Дельфи обсуждаем здесь
  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Вопросы по реализации алгоритмов рассматриваются здесь
  • 90% ответов на свои вопросы можно найти в DRKB (Delphi Russian Knowledge Base) - крупнейшем в рунете сборнике материалов по Дельфи


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Snowy, MetalFan, bems, Poseidon, Rrader.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Delphi: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.0541 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.