Главная страница
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.48 MB
Время: 0.016 c
3-84026
paulsin
2003-05-31 19:52
2003.06.26
SQL функция TOP


1-84148
Comp
2003-06-11 12:40
2003.06.26
Как прокручивать часть формы её собственными полосами прокрутки?


8-84447
Sder
2003-03-09 11:23
2003.06.26
Вы случайно не знаете как в delphi получить avi из последовательн


7-84786
_ALEXey_
2003-04-09 19:03
2003.06.26
Запрет всех контекстных меню в системе (ловушка)


1-84385
VISA
2003-06-09 11:58
2003.06.26
TIniFile