Вниз
Скачать: 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 вся ветка

Скачать: CL | DM;



Память: 0.46 MB
Время: 0.016 c
14-84682
miwa
2003-06-09 15:53
2003.06.26
Поругаем винду?


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


1-84268
Ajax
2003-06-13 21:10
2003.06.26
Интересный глюк...


3-83903
RazorbladE
2003-06-03 11:52
2003.06.26
Отображение данных из SQL запроса dbExpress MySQL.


14-84577
Sam
2003-06-07 19:35
2003.06.26
Hosting for Delphi




   Наверх