我在D6+Winxp SP2下编写了以下程序,请问两个Edit的内容怎么不同步更新呢?
unit test1;interfaceuses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, ComCtrls;type
TForm1 = class(TForm)
Edit1: TEdit;
Edit2: TEdit;
Label1: TLabel;
Label2: TLabel;
TrackBar1: TTrackBar;
TrackBar2: TTrackBar;
Label3: TLabel;
Label4: TLabel;
Button1: TButton;
Button2: TButton;
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end; TMyThread=class(tthread)
Fm,Fn:integer;
FEdit:TEdit;
procedure Show;
constructor create(m,n:Integer;myEdit:TEdit);
procedure execute;override;
end;
var
Form1: TForm1;implementation{$R *.dfm}{ TMyThread }constructor TMyThread.create(m, n: Integer; myEdit: TEdit);
begin
inherited create(false);
Fm:=m;
Fn:=n;
FEdit:=myEdit;
freeonterminate:=true; // 线程终止时自动删除对象,
end;procedure TMyThread.execute;
begin
synchronize(show); // 线程调用同步
end;procedure TMyThread.Show;
var
i:Integer;
begin
for i:=Fm to Fn do
begin
FEdit.Text:='循环到:'+IntToStr(i);
FEdit.Update;
end;
end;procedure TForm1.Button1Click(Sender: TObject);
var
T1,T2:TmyThread;
begin
Edit1.Text:='';
Edit2.Text:='';
T1:=TMyThread.create(1,20000,Edit1);
T2:=TMyThread.create(20001,50000,Edit2);
end;end.
unit test1;interfaceuses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, ComCtrls;type
TForm1 = class(TForm)
Edit1: TEdit;
Edit2: TEdit;
Label1: TLabel;
Label2: TLabel;
TrackBar1: TTrackBar;
TrackBar2: TTrackBar;
Label3: TLabel;
Label4: TLabel;
Button1: TButton;
Button2: TButton;
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end; TMyThread=class(tthread)
Fm,Fn:integer;
FEdit:TEdit;
procedure Show;
constructor create(m,n:Integer;myEdit:TEdit);
procedure execute;override;
end;
var
Form1: TForm1;implementation{$R *.dfm}{ TMyThread }constructor TMyThread.create(m, n: Integer; myEdit: TEdit);
begin
inherited create(false);
Fm:=m;
Fn:=n;
FEdit:=myEdit;
freeonterminate:=true; // 线程终止时自动删除对象,
end;procedure TMyThread.execute;
begin
synchronize(show); // 线程调用同步
end;procedure TMyThread.Show;
var
i:Integer;
begin
for i:=Fm to Fn do
begin
FEdit.Text:='循环到:'+IntToStr(i);
FEdit.Update;
end;
end;procedure TForm1.Button1Click(Sender: TObject);
var
T1,T2:TmyThread;
begin
Edit1.Text:='';
Edit2.Text:='';
T1:=TMyThread.create(1,20000,Edit1);
T2:=TMyThread.create(20001,50000,Edit2);
end;end.
FEdit.Text:= '循环到: '+IntToStr(i);
FEdit.Update;
写到另一个函数中,如:
procedure XXX.UpdateEditor;
begin
FEdit.Text:= '循环到: '+IntToStr(i);
FEdit.Update;
end;
再在循环体中这样调用:
procedure TMyThread.Show;
var
i:Integer;
begin
for i:=Fm to Fn do
begin
synchronize(UpdateEditor);
end;
end;
TMyThread=class(tthread)
Fm,Fn: Integer;
FEdit: TEdit;
i : Integer;
procedure Show;
constructor create(m,n:Integer;myEdit:TEdit);
procedure execute;override;
end; procedure TMyThread.execute;
begin
for i := Fm to Fn do
synchronize(show);
end; procedure TMyThread.Show;
begin
FEdit.Text:= '循环到: ' + IntToStr(i);
FEdit.Update;
end;
TMyThread=class(tthread)
Fm,Fn:integer;
FEdit:TEdit;
Fi : Integer;
procedure Show;
constructor create(m,n:Integer;myEdit:TEdit);
procedure execute;override;
end;
procedure TMyThread.execute;
var
i : Integer;
begin
for i := Fm to Fn do
begin
Fi := i;
synchronize(show);
end;
end;procedure TMyThread.Show;
begin
FEdit.Text:= 循环到:'+IntToStr(Fi);
FEdit.Update;
end;你试一下就知道这样的代码是不是符合你的要求了。
=========================
他们两人的代码机制上面是有所差别的,如果不相信可以使用Spy++进行消息跟踪。
流水线也好,多核CPU也好,总要通过时间片来管理的,与其说“消息机制”,不如说控制临界资源好理解。synchronize就是用来处理VCL相关临界资源的,所以把VCL访问的代码放入到synchronize的函数中就行了。简单吧。
==================
多核讲求的就是多个线程同一时间片同并行执行,就好比两工人在工作。
另外我所说的多核跟Synchronize是两回事。
如果不懂得Synchronize的原理,可以看一下VCL当中相关的实现代码,或者搜索一下这个版块当中别的地址,前一段时间还有人专程发出相关的线程同步的贴子进行过讨论。http://topic.csdn.net/u/20070531/17/7c410df9-4aa5-4ed0-9227-159caedbad9a.html另外对于应用程序当中多线程的执行,既然这里面使用的是C++的代码,建议可以采用VC++/Intel C++进行编译,然后使用Intel的一个Thread Profiler相关工具进行线程执行流水线的分析。PS:
1.我这并不是给Intel打广告,仅仅只是提供一种途径来了解多线程的运行状态。
2.我上面说的要进行多线程的并行,而没有提Synchronize,只是为了解答楼主的问题,所以没有提出VCL的同步问题。实际上,在这样一个简单的程序当中完全可以不使用VCL同步,因为在这里面不会有多个线程对同一个Edit进行改写。线程同步需要同步的只是避免多个线程的写竞争。
对于unsigned提到的一个核(CPU),实际程序只能串行执行的问题,我又加了几句代码,用GetTickcount测试了在用多线程(如上代码)和在非多线程(如下)代码下执行的时间,发现在非多线程下的效率还要快些。我的疑惑是:还有必要使用多线程吗?(费话,肯定有必要了)那在哪些情况下需要用多线程来实现呢?
procedure TForm1.Button2Click(Sender: TObject);
var
i:Integer;
begin
T_start:=GetTickCount;
for i:=1 to 20000 do
begin
Edit1.Text:='循环到:'+IntToStr(i);
Edit1.Update;
end;
for i:=20001 to 40000 do
begin
Edit2.Text:='循环到:'+IntToStr(i);
Edit2.Update;
end;
ShowMessage(IntToStr(GetTickCount-T_start));
end;
比如楼上的问题当中,实际上很显而易见的就是把一个大的循环作业分成多个线程去做。通常情况下我们说,一个循环,只要前一步运算结果与后一步的运算结果互不影响(不是没有联系)就可以把它分成多个任务,从而让多个人,在这里可以假定为多台电脑(如果运算强度比较大的话,这也是可行的)去完成。在同一台机器上面,则我们说得比较多的就是多进程和多线程,而对于进程来讲,分配的资源会比较多,并且启动和销毁,数据同步等开销相当大,所以在能使用多线程的情况下尽可能采用多线程。但是线程也并不是越多越好,否则的话,多个线程共享同一个CPU,那么指令在CPU当中同样是串行的,而这个线程的切换是有相当开销的,反倒有可能引起性能下降。而推荐的情况就是当没有低速设备参与的情况下,一般地就是根据CPU的并行能力,通俗一点,就目前来讲,那就是逻辑核个数。这样子才能达到真正并行处理的目的。