这个多线程怎么不同步执行?
我在D6+Winxp SP2下编写了以下程序,请问两个Edit的内容怎么不同步更新呢?
unit test1;
interface
uses
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.
[解决办法]
把循环放在execute中,而不是Show中:
type
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;
[解决办法]
我所说的和 seamansoft 就是不一样的哇。 你没明白synchronize的原理,所以才会有这样的疑问。
在execute中代码是按线程的方式运作的,也就是说它们是并行工作的。用synchronize调用的代码是在主线程中以消息机制、按串行方式工作的。你把循环放在synchronize中去执行的话,一个循环结束之前,另一个循环是不会开始的。
当然,我上面给出的代码也有些问题,就是循环变量得是局部变量。修改如下:
type
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;
你试一下就知道这样的代码是不是符合你的要求了。
[解决办法]
多线程使用的必要性当中的什么等待慢速设备之类的,我就不多提了,各式各样的资料当中都有说明。
比如楼上的问题当中,实际上很显而易见的就是把一个大的循环作业分成多个线程去做。通常情况下我们说,一个循环,只要前一步运算结果与后一步的运算结果互不影响(不是没有联系)就可以把它分成多个任务,从而让多个人,在这里可以假定为多台电脑(如果运算强度比较大的话,这也是可行的)去完成。在同一台机器上面,则我们说得比较多的就是多进程和多线程,而对于进程来讲,分配的资源会比较多,并且启动和销毁,数据同步等开销相当大,所以在能使用多线程的情况下尽可能采用多线程。但是线程也并不是越多越好,否则的话,多个线程共享同一个CPU,那么指令在CPU当中同样是串行的,而这个线程的切换是有相当开销的,反倒有可能引起性能下降。而推荐的情况就是当没有低速设备参与的情况下,一般地就是根据CPU的并行能力,通俗一点,就目前来讲,那就是逻辑核个数。这样子才能达到真正并行处理的目的。