Форум: "Основная";
Текущий архив: 2003.06.26;
Скачать: [xml.tar.bz2];
ВнизСтранный глюк при выходе из критической секции Найти похожие ветки
← →
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;
Скачать: [xml.tar.bz2];
Память: 0.45 MB
Время: 0.03 c