Delphi - Обновление глобальной строки из второго потока

Я экспериментирую с многопоточностью в Delphi (XE) и столкнулся с проблемой с использованием глобальной переменной между основным потоком VCL и вторым рабочим потоком.

В моем проекте задействован второй рабочий поток, который просматривает некоторые файлы и обновляет строку globalvar с текущим именем файла. Затем эта глобальная переменная выбирается таймером в основном потоке VCL и обновляет строку состояния.

Я заметил, что иногда возникает ошибка «Недопустимая операция указателя» ... или «Недостаточно памяти», или рабочий поток просто перестает отвечать (возможно, тупик).

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

type
  TSyncThread = class(TThread)
  protected
    procedure Execute; override;
end;

var
  Form11: TForm11;
  ProgressString : String;
  ProgressCount : Int64;
  SyncThread : TSyncThread;
  CritSect : TRTLCriticalSection;

implementation

{$R *.dfm}

procedure TForm11.StartButtonClick(Sender: TObject);
begin
  Timer1.Enabled := true;
  SyncThread := TSyncThread.Create(True);
  SyncThread.Start;
end;

procedure TForm11.StopbuttonClick(Sender: TObject);
begin
  Timer1.Enabled := false;
  SyncThread.Terminate;
end;

procedure TForm11.Timer1Timer(Sender: TObject);
begin
  StatusBar1.Panels[0].Text := 'Count: ' + IntToStr(ProgressCount);
  StatusBar1.Panels[1].Text := ProgressString;
end;

procedure TSyncThread.Execute;
var
  i : Int64;
begin
  i := 0;
  while not Terminated do begin
    inc(i);
    EnterCriticalSection(CritSect);
    ProgressString := IntToStr(i);
    ProgressCount := i;
    LeaveCriticalSection(CritSect);
  end;
end;

initialization
  InitializeCriticalSection(CritSect);
finalization
  DeleteCriticalSection(CritSect);

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

У меня вопрос: нужно ли выполнять операцию чтения глобальной переменной в таймере VCL в критическом разделе? - если да, то почему ?. Насколько я понимаю, это только чтение, и, поскольку записи уже выполняются в критическом разделе, я не могу понять, почему это вызывает проблему. Если я все же помещаю показания таймера в критическую секцию - все работает нормально ....но я недоволен тем, что делаю это, не зная почему!

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

9
задан froudeg 15 October 2011 в 16:42
поделиться

0 ответов

Другие вопросы по тегам:

Похожие вопросы: