线程中临界区对象(TCriticalSection)不起作用
求助:线程中临界区对象(TCriticalSection)不起作用。
写了个数据处理线程,处理结果输出到一个TMemo对象,为避免显示混乱,设立了一个临界区,控制输出过程,开始输出到输出结束之间的代码由临界区负责保护,但是我发现,临界区完全没有作用,怎么回事?
线程代码:
调用代码:
求助一下,为什么只要按下Button5,Mmo1上就会输出新设置进去的数据?
我原先设想是:第一次按下Button5,Mmo1上显示数据,修改edit1的数据,再次点下Button5,新数据不会被输出到Mmo1上,点Button6后,才会在Mmo1上输出新设的数据。
我的环境是WinXP sp3,delphi6,谢谢。
------解决思路----------------------
我原先设想是:第一次按下Button5,Mmo1上显示数据,修改edit1的数据,再次点下Button5,新数据不会被输出到Mmo1上,点Button6后,才会在Mmo1上输出新设的数据。
这种应用,用信号明显要合适点,用TCriticalSection,要麻烦些
procedure Tb.Execute;
begin
inherited;
while True do
begin
Synchronize(showmm);
Application.ProcessMessages ;
end;
end;
这是让某一个CPU一直运行的节奏,不好,
------解决思路----------------------
这个代码给你掩饰临界区的作用,如果注释掉for循环中的临界区那2句,看结果是否=60000000,同时可以看到怎么显示同步到主线程操作界面控件
------解决思路----------------------
线程实际执行的代码只是EXCUTE部分,其它不被excute调用的代码,都是主线程执行的。所以几个线程锁和解锁的对象,只能在excute才有意义
------解决思路----------------------
建议你把进程中跟界面相关的放在一个线程中处理。除非你有非常复杂的UI渲染。其他线程不要处理窗口消息相关的东西,做完辅助工作要通知界面时,用发windows消息的方式告诉主线程。
用Synchronize()方法同步给主线程做事一个很别扭的不正常的方式。不知道borland当初为啥会想出一个这样的方法来。可能是为了满足小白的需求吧。
------解决思路----------------------
线程与主线程之间几乎是隔绝的,线程中是不能对主线程进行操作。必须通过消息才能处理。
------解决思路----------------------
这写法,我是真没有弄懂。临界的概念与用途,还没有明白,先学学,生产者与消者费的模式
写了个数据处理线程,处理结果输出到一个TMemo对象,为避免显示混乱,设立了一个临界区,控制输出过程,开始输出到输出结束之间的代码由临界区负责保护,但是我发现,临界区完全没有作用,怎么回事?
线程代码:
Tb = class(TThread)
private
CS: TCriticalSection; //临界区对象
mm: TMemo; //用于显示的memo
fshowvalue: string; //用于显示的数据
procedure showmm(); //显示数据过程
procedure setshowvalue(const Value: string); //设置显示数据的过程
protected
procedure Execute; override;
public
constructor Create(mmo: TMemo); //创建时传入显示控件
destructor Destroy; override;
procedure Next(); //显示下一个输入的数据
property showvalue: string read fshowvalue write setshowvalue;//设置显示的数据
end;
implementation
{ Tb }
constructor Tb.Create(mmo: TMemo);
begin
inherited Create(True);
mm := mmo;
CS := TCriticalSection.Create;
fshowvalue := '';
Resume;
end;
destructor Tb.Destroy;
begin
CS.Leave;
CS.Free ;
inherited;
end;
procedure Tb.Execute;
begin
inherited;
while True do
begin
Synchronize(showmm);
Application.ProcessMessages ;
end;
end;
procedure Tb.showmm;
begin
if fshowvalue <> '' then //不输出空串
mm.Lines.Add(fshowvalue);
end;
procedure Tb.Next;
begin
CS.Leave ; //离开临界区
end;
procedure Tb.setshowvalue(const Value: string);
begin
CS.Enter; //进入临界区,应该只要没有离开临界区,这段
//代码就不应该被重复执行,而是等待上次调用
//离开临界区
//但实际上,只要进入这个过程就会往下执行,
//临界区对象似乎完全没有作用,为什么???
mm.Lines.Clear;
fshowvalue := Value;
end;
调用代码:
procedure TForm1.FormCreate(Sender: TObject);
begin
bb := Tb.Create(Mmo1); //创建线程
end;
procedure TForm1.Button5Click(Sender: TObject);
begin
bb.showvalue := Edit1.Text ; //设置要显示的数据
end;
procedure TForm1.Button6Click(Sender: TObject);
begin
bb.Next ; //显示下一个数据
end;
求助一下,为什么只要按下Button5,Mmo1上就会输出新设置进去的数据?
我原先设想是:第一次按下Button5,Mmo1上显示数据,修改edit1的数据,再次点下Button5,新数据不会被输出到Mmo1上,点Button6后,才会在Mmo1上输出新设的数据。
我的环境是WinXP sp3,delphi6,谢谢。
------解决思路----------------------
我原先设想是:第一次按下Button5,Mmo1上显示数据,修改edit1的数据,再次点下Button5,新数据不会被输出到Mmo1上,点Button6后,才会在Mmo1上输出新设的数据。
这种应用,用信号明显要合适点,用TCriticalSection,要麻烦些
procedure Tb.Execute;
begin
inherited;
while True do
begin
Synchronize(showmm);
Application.ProcessMessages ;
end;
end;
这是让某一个CPU一直运行的节奏,不好,
------解决思路----------------------
type
TForm1 = class(TForm)
Memo1: TMemo;
procedure FormCreate(Sender: TObject);
private
procedure DoShowData;
public
end;
var
Form1: TForm1;
CS: TCriticalSection;
dwDest : LongWord;
dwThreadCount : integer;
implementation
{$R *.dfm}
type
TAddThread = class(TThread)
private
protected
procedure Execute; override;
end;
procedure TAddThread.Execute;
var
i : integer;
begin
FreeOnTerminate := True;
CS.Enter;
Inc(dwThreadCount); //线程计数,多少个线程进入
CS.Leave;
for i := 1 to 30000000 do begin
CS.Enter; //如果注释掉这句和Leave那句,看结果
dwDest := dwDest + 1;
CS.Leave; //如果注释掉这句和Leave那句,看结果
end;
CS.Enter;
Dec(dwThreadCount);
if dwThreadCount=0 then //最后一个结束的线程显示数据
Synchronize(Form1.DoShowData);
CS.Leave;
end;
procedure TForm1.DoShowData;
begin
Memo1.Lines.Add(IntToStr(dwDest));
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
dwDest := 0;
CS := TCriticalSection.Create;
TAddThread.Create;
TAddThread.Create;
end;
这个代码给你掩饰临界区的作用,如果注释掉for循环中的临界区那2句,看结果是否=60000000,同时可以看到怎么显示同步到主线程操作界面控件
------解决思路----------------------
线程实际执行的代码只是EXCUTE部分,其它不被excute调用的代码,都是主线程执行的。所以几个线程锁和解锁的对象,只能在excute才有意义
------解决思路----------------------
建议你把进程中跟界面相关的放在一个线程中处理。除非你有非常复杂的UI渲染。其他线程不要处理窗口消息相关的东西,做完辅助工作要通知界面时,用发windows消息的方式告诉主线程。
用Synchronize()方法同步给主线程做事一个很别扭的不正常的方式。不知道borland当初为啥会想出一个这样的方法来。可能是为了满足小白的需求吧。
------解决思路----------------------
线程与主线程之间几乎是隔绝的,线程中是不能对主线程进行操作。必须通过消息才能处理。
------解决思路----------------------
这写法,我是真没有弄懂。临界的概念与用途,还没有明白,先学学,生产者与消者费的模式