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

Вниз

Странный глюк при выходе из критической секции   Найти похожие ветки 

 
alexvan ©   (2003-06-16 10:13) [0]

У меня эта штука работает в XP и отказывается работать под WinME

unit twothreads;

interface

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

type
TMainForm = class(TForm)
Button1: TButton;
ListBox1: TListBox;
procedure Button1Click(Sender: TObject);
private
procedure ThreadsDone(Sender: TObject);
end;

TFooThread = class(TThread)
protected
procedure Execute; override;
end;

var
MainForm: TMainForm;

implementation

{$R *.dfm}

const
MaxSize = 128;

var
NextNumber: Integer = 0;
DoneFlags: Integer = 0;
GlobalArray: array[1..MaxSize] of Integer;
CS: TRTLCriticalSection;

function GetNextNumber: Integer;
begin
Result:=NextNumber;
Inc(NextNumber);
end;

procedure TFooThread.Execute;
var
i: Integer;
begin
OnTerminate := MainForm.ThreadsDone;
EnterCriticalSection(CS);
for i := 1 to MaxSize do
begin
GlobalArray[i] := GetNextNumber;
Sleep(5);
end;
LeaveCriticalSection(CS);
end;

procedure TMainForm.ThreadsDone(Sender: TObject);
var
i: Integer;
begin
Inc(DoneFlags);
if DoneFlags = 2 then
for i:=1 to MaxSize do
ListBox1.Items.Add(IntToStr(GlobalArray[i]));
DeleteCriticalSection(CS);
end;

procedure TMainForm.Button1Click(Sender: TObject);
begin
InitializeCriticalSection(CS);
TFooThread.Create(False);
TFooThread.Create(False);
end;

end.


 
Digitman ©   (2003-06-16 10:42) [1]

В то время как в осн.потоке выполняется
ListBox1.Items.Add(IntToStr(GlobalArray[i])); (чтение эл-та массива)

в одном из доп.потоков в это время вполне может происходить
GlobalArray[i] := GetNextNumber; (запись того же эл-та массива)

Нонсенс ? Разумеется !

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





 
alexvan ©   (2003-06-16 10:47) [2]

Ошибка была вот в чём
if DoneFlags = 2 then
begin
for i:=1 to MaxSize do
ListBox1.Items.Add(IntToStr(GlobalArray[i]));
DeleteCriticalSection(CS);
end
</CODE


 
Digitman ©   (2003-06-16 11:03) [3]

все равно некорректно.

вот так в общем случае будет правильней :

procedure TMainForm.ThreadsDone(Sender: TObject);
var
i: Integer;
begin
EnterCriticalSection(CS); // другой поток вполне в этот момент может осуществлять доступ к ресурсу ! Необходим захват секции
try
for i:=1 to MaxSize do
ListBox1.Items.Add(IntToStr(GlobalArray[i]));
finally
LeaveCriticalSection(CS); // поработали с ресурсом - освободили секцию
Inc(DoneFlags);
if DoneFlags = 2 then /// потоков м.б. и 2 и 2000 и ...
DeleteCriticalSection(CS); // этот поток - последний осуществивший доступ к ресурсу, вот теперь можно и удалить секцию
end;
end;


 
alexvan ©   (2003-06-16 11:16) [4]

ОК. Спасибо



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

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

Наверх




Память: 0.47 MB
Время: 0.015 c
7-84791
Дельфятник
2003-04-18 11:05
2003.06.26
Какие события надо ловить чтобы программа реагировала на то, (+)


3-84038
korvin
2003-06-01 07:17
2003.06.26
Не дать


3-83872
Dem
2003-06-02 12:06
2003.06.26
Как создать пароль на базу данных


14-84519
Nox
2003-06-01 13:39
2003.06.26
DISABLEKERNEL


1-84152
McSimm2
2003-06-11 10:33
2003.06.26
Плавный переход цвета из одного в другой