我的程序意图很简单,就是form1的界面多个listbox(记录下线程曾经获得的值),和2个edit(分别给起始值和终点值)。噢,有个遗漏就是:还有个执行按钮,吼吼unit Unit2;interfaceuses
Classes,SysUtils;type
myFun = class(TThread)
private
{ Private declarations }
FStartID,FEndID: Integer; //定义变量? 和FStartID之间存在某种不正当关系?
procedure UpdateList; //定义自己的更新UI函数 protected
procedure Execute; override;
public
property StartID:Integer read FStartID write FStartID; //定义类的属性StartID ?
property EndID:Integer read FEndID write FEndID; //定义类的属性EndID ?
end;implementation
uses Unit1,Dialogs;//--------好像必须引用Unit1,否则Form1.Listbox1.Items报错 ? 我看笑青天兄弟给人留的代码,就灭有引用,偶不明白究理
{ Important: Methods and properties of objects in visual components can only be
used in a method called using Synchronize, for example, Synchronize(UpdateCaption); and UpdateCaption could look like, procedure myFun.UpdateCaption;
begin
Form1.Caption := 'Updated in a thread';
end; }{ myFun }procedure myFun.UpdateList;
begin
case StartID mod 3 of
1:
begin
Form1.Listbox1.Items.Add(IntToStr(FStartID));
Form1.ListBox1.ItemIndex := Form1.ListBox1.Items.Count - 1;
end;
2:
begin
showmessage(IntToStr(FStartID));
Unit1.Form1.Listbox2.Items.Add(IntToStr(FStartID));
Unit1.Form1.ListBox2.ItemIndex := Unit1.Form1.ListBox2.Items.Count - 1;
Form1.Edit3.Text := IntToStr(FStartID);
Unit1.Form1.ListBox2.Refresh;
end;
end;
end;procedure myFun.Execute;
begin
{ Place thread code here }
FreeOnTerminate:=True; FStartID := StartID;
while FStartID < EndID do
begin
//执行代码
Synchronize(UpdateList);
FStartID := FStartID + 100;
end;end;end.调用线程的代码implementationuses Unit2;//-------------------好像也必须引用,否则myFun.create出错?
{$R *.dfm}procedure TForm1.Button1Click(Sender: TObject);
var
Test:myFun;
begin Test := myFun.Create(True);//创建一个线程,若有多个线程,依次创建
Test.StartID := StrToInt(Edit1.Text ); //起始值给23
Test.EndID := StrToInt(Edit2.Text ); //终点值给2000,按想法应该listbox2应该有23,123,223,323……,1923的一个值的列表出来,结果什么都灭有
Test.Resume;end;
很多疑问都在注释部分描述了,请大侠给偶讲解,100分相酬,偶用的D2007,不知道是否有影响……
Classes,SysUtils;type
myFun = class(TThread)
private
{ Private declarations }
FStartID,FEndID: Integer; //定义变量? 和FStartID之间存在某种不正当关系?
procedure UpdateList; //定义自己的更新UI函数 protected
procedure Execute; override;
public
property StartID:Integer read FStartID write FStartID; //定义类的属性StartID ?
property EndID:Integer read FEndID write FEndID; //定义类的属性EndID ?
end;implementation
uses Unit1,Dialogs;//--------好像必须引用Unit1,否则Form1.Listbox1.Items报错 ? 我看笑青天兄弟给人留的代码,就灭有引用,偶不明白究理
{ Important: Methods and properties of objects in visual components can only be
used in a method called using Synchronize, for example, Synchronize(UpdateCaption); and UpdateCaption could look like, procedure myFun.UpdateCaption;
begin
Form1.Caption := 'Updated in a thread';
end; }{ myFun }procedure myFun.UpdateList;
begin
case StartID mod 3 of
1:
begin
Form1.Listbox1.Items.Add(IntToStr(FStartID));
Form1.ListBox1.ItemIndex := Form1.ListBox1.Items.Count - 1;
end;
2:
begin
showmessage(IntToStr(FStartID));
Unit1.Form1.Listbox2.Items.Add(IntToStr(FStartID));
Unit1.Form1.ListBox2.ItemIndex := Unit1.Form1.ListBox2.Items.Count - 1;
Form1.Edit3.Text := IntToStr(FStartID);
Unit1.Form1.ListBox2.Refresh;
end;
end;
end;procedure myFun.Execute;
begin
{ Place thread code here }
FreeOnTerminate:=True; FStartID := StartID;
while FStartID < EndID do
begin
//执行代码
Synchronize(UpdateList);
FStartID := FStartID + 100;
end;end;end.调用线程的代码implementationuses Unit2;//-------------------好像也必须引用,否则myFun.create出错?
{$R *.dfm}procedure TForm1.Button1Click(Sender: TObject);
var
Test:myFun;
begin Test := myFun.Create(True);//创建一个线程,若有多个线程,依次创建
Test.StartID := StrToInt(Edit1.Text ); //起始值给23
Test.EndID := StrToInt(Edit2.Text ); //终点值给2000,按想法应该listbox2应该有23,123,223,323……,1923的一个值的列表出来,结果什么都灭有
Test.Resume;end;
很多疑问都在注释部分描述了,请大侠给偶讲解,100分相酬,偶用的D2007,不知道是否有影响……
解决方案 »
- 请教delphi中combobox的问题
- integer类型可以赋成3500000?!!
- 急....导入到EXCEL中是如何进行合并两列????
- How to Control the fsMDIChild Form 's Position and Size?
- 询问广州诚毅软件(立信企业下属单位)
- 我喜欢的MM要去深圳,我想让她走啊,我改怎么办?大家救救我吧!
- 怎样对应字段导数据
- 最白吃的问题!!!在线等!!急!!@ var Form1: TForm1;这个定义去掉有事吗???
- 说起Borland真是很无奈
- 如何最小安装BDE?
- Error: Negative or void server response
- 求助,如何在delphi中添加TCP socket 组件
unit Unit2;interfaceuses
Classes,SysUtils;type
TMyFun = class(TThread)
private
{ Private declarations }
FStartID,FEndID: Integer;
FStringList:TStrings;
procedure UpdateList;
procedure HookListBox;
protected
procedure Execute; override;
public
constructor Create(CreateSuspended: Boolean);
destructor Destroy; override;
published
property StartID:Integer read FStartID write FStartID;
property EndID:Integer read FEndID write FEndID;
end;implementationuses Unit1;constructor TMyFun.Create(CreateSuspended: Boolean);
begin
inherited Create(CreateSuspended);
FStringList:=TStringList.Create;end;destructor TMyFun.Destroy;
begin
FreeAndNil(FStringList);
inherited;
end;procedure TMyFun.Execute;
begin
FreeOnTerminate:=True;
UpdateList;
Synchronize(HookListBox);
{ Place thread code here }
end;procedure TMyFun.HookListBox;
begin
Form1.ListBox1.Items:=FStringList;
end;procedure TMyFun.UpdateList;
begin
while StartID<EndID do
begin
case StartID mod 3 of
1:
FStringList.Add(IntToStr(StartID));
2:
FStringList.Add(IntToStr(StartID));
end;
Sleep(10);
StartID := StartID + 100;
end;
end;end.
//主程序
procedure TForm1.Button1Click(Sender: TObject);
var
Test:TMyFun;
begin
Test:=TMyFun.Create(True);
Test.StartID:=23;
Test.EndID:=2000;
Test.Resume;end;
//这样写还不如写在主线程中!procedure myFun.Execute;
begin
{ Place thread code here }
FreeOnTerminate:=True; FStartID := StartID;
while FStartID < EndID do
begin
//执行代码
Synchronize(UpdateList);
FStartID := FStartID + 100;
end;end;
吼吼,我看了下delphi开发人员指南的电子书籍,然后也看到了兄弟答复别人的问题中举例的代码
有些地方不是很明白,所以在注释中给描述了偶的困惑,请兄弟讲解下了?另外,为什么不如写在主线程中呢?我只是举例性质的只产生了一个线程,我最终的想法是多个线程的……请帮忙答疑解惑下偶关于代码中的不解的地方,主要都在注释中给描述了
谢谢啊
FStartID,FEndID: Integer; //定义变量? 和FStartID之间存在某种不正当关系?
这个是偶的一个困惑,不太明白
问题2uses Unit1,Dialogs;//--------好像必须引用Unit1,否则Form1.Listbox1.Items报错 ? 我看笑青天兄弟给人留的代码,就灭有引用,偶不明白究理uses Unit2;//-------------------好像也必须引用,否则myFun.create出错?这2个引用的地方,好像构成了循环应用,我看开发指南里面说这种是不提倡的,也就是说肯定不规范了,为什么偶会出现这个问题呢?该如何归还呢?
问题3而兄弟给别人留的代码里面edit对象是直接个值,为什么listbox就需要多个FStringList函数,多个FStringList---》偶个人看法是就算偶的东西不对
会导致重复添加listbox里面的item进去,但是也该有个结果啊,兄弟的方法是用FStringList保存了所有的结果,一次性的赋值给了listbox所以,为什么偶的执行结果是messagebox有正确提示值,但是listbox2始终是灭有添加进去,也不报错?
问题2的最后是想问,该如何来规范它问题3的开始是说兄弟给别人留的代码里面,如果是给edit对象赋值,就直接给的,为什么listbox要多个函数,和多一个FStringList嗯,新手学习过程中,可能让高手感觉幼稚可笑,还请不吝赐教啊,分不是问题,问题是一定要搞个明白
1.有点看不懂,我猜你是想问既然有了FStartID为何要用 StartID?因为我是想在类外直接对类内的值进行赋值
2.
3.Synchronize是将线程并行转串行的,也就是委托主线程做界面控制的操作,因为VCL大部分控件都是假设单线程访问而设计的,你在向LIST中添加记录时,你的程序写的是直接把循环任务交给主线程干了,这和单线程有什么区别?所以要保证把费时,容易堵主线程的任务交给线程做。要Synchronize的函数只需要做一个界面连接即可,一般情况下做一些数据连接什么的!
procedure myFun.Execute;
begin
{ Place thread code here }
FreeOnTerminate:=True; FStartID := StartID;
while FStartID < EndID do
begin
//执行代码
Synchronize(UpdateList); //频繁地在子线程与主线程之间切换,效率不同
FStartID := FStartID + 100;
end;end;
假设我创建2个进程,一个算奇数,一个算偶数
定义部分procedure TMyFun.UpdateList;
begin
while StartID<EndID do
begin
case StartID mod 2 of
0:
FStringList.Add(IntToStr(StartID));
1:
FStringList.Add(IntToStr(StartID));
end;
Sleep(10);
StartID := StartID + 2;
end;
end;调用部分
[code=Delphi(Pascal)]
Test1:=TMyFun.Create(True);
Test1.StartID:=1;
Test1.EndID:=999999999999999999999; //姑且不考虑int的溢出这些问题
Test1.Resume; Test2:=TMyFun.Create(True);
Test2.StartID:=2;
Test2.EndID:=999999999999999999999; //姑且不考虑int的溢出这些问题
Test2.Resume;我这个举例计算的过程相对较长,从1到999999999999999999999 (例子是2个进程,有可能更多)
我希望能在进度条上比较及时和准确的反馈当前的整体进度(2个线程目前总共完成了整体20% ...30%或者33%)这个又该如何操作了呢?
如:
把计算操作放在子线程中:
1.根据数据量定一个最大值!
2.每计算一个阶段后,用PostThreadMessage把进度条加1的消息传给UI线程,UI线程根据消息加1后刷新当前进度!
如果频繁地用Synchronize只会增加系统开销
本例来实现用线程做进度条unit Unit2;interfaceuses
Classes,SysUtils,Windows,CommCtrl;type
TMyFun = class(TThread)
private
{ Private declarations }
FStartID,FEndID: Integer;
FStringList:TStrings;
procedure UpdateList;
procedure HookListBox(Value:Integer);
protected
procedure Execute; override;
public
constructor Create(CreateSuspended: Boolean);
destructor Destroy; override;
published
property StartID:Integer read FStartID write FStartID;
property EndID:Integer read FEndID write FEndID;
end;implementationuses Unit1;constructor TMyFun.Create(CreateSuspended: Boolean);
begin
inherited Create(CreateSuspended);
FStringList:=TStringList.Create;end;destructor TMyFun.Destroy;
begin
FreeAndNil(FStringList);
inherited;
end;procedure TMyFun.Execute;
begin
FreeOnTerminate:=True;
UpdateList;
{ Place thread code here }
end;procedure TMyFun.HookListBox(Value:Integer);
begin
PostMessage(Form1.ProgressBar1.Handle,PBM_SETPOS,Value,0);
end;procedure TMyFun.UpdateList;
begin
while StartID<EndID do
begin
case StartID mod 3 of
1:
FStringList.Add(IntToStr(StartID));
2:
FStringList.Add(IntToStr(StartID));
end;
Sleep(10);
//========================
注意这条语句,要想实时显示进度可以用Synchronize,但如果把该语句放到循环中,你测试一下,主窗体将不能动!
这是因为进程频繁地在主线程与子线程之间切换,效率很低,如果说极端点,这就相当于在主线程中做了这个工作,
我不知道我说明白了没有。所以线程也要慎用。
而用消息机制来处理的话就省去了这些操作,直接在子线程中发送信息给UI线程,由UI线程来控制进度。
你肯定要问我如何能得知进度条增1或减1的消息,你可以直接查看一下TProgressBar的源码,定位到STEPIT过程,该过程中就是用消息来处理的。
我不知道这样找正确不正确,反正我是这么找出来的:)
HookListBox(StartID);
//========================
StartID := StartID + 1;
end;
end;end.
//说错了,是SetPosition的源码
以上源码可能写的不严密,其侧重点主要是说明用消息来传递的功能
另:我也是刚学没几天,有不对的地方请大家指正
procedure TProgressBar.SetPosition(Value: Integer);
begin
if not F32BitMode and ((Value < 0) or (Value > Limit16)) then
ProgressLimitError;
if HandleAllocated then SendMessage(Handle, PBM_SETPOS, Value, 0)
else FPosition := Value;
end;