在启动软件时,需要打开多个窗体,且每个窗体的打开时间都较长,因此为了界面友好,首先打开主窗体,并在主窗体上设置了进度条,在进度条不断滚动的情况下,使用多线程类打开其他窗体。问题是,使用多线程类打开其他窗体时软件总是死机。主窗体界面如下:
主窗体代码如下:
unit uInitForms;interfaceuses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, ComCtrls, ExtCtrls, ADODB, Buttons;type
TfrmInitForms = class(TForm)
GroupBox1: TGroupBox;
lblInMainList: TLabel;
lblInSearch: TLabel;
lblOutMainList: TLabel;
lblBillManage: TLabel;
pbInMainList: TProgressBar;
pbInSearch: TProgressBar;
pbOutMainList: TProgressBar;
pbBillManage: TProgressBar;
Timer1: TTimer;
pbOutSearch: TProgressBar;
lblOutSearch: TLabel;
procedure Button1Click(Sender: TObject);
procedure btnUploadClick(Sender: TObject);
procedure FormDestroy(Sender: TObject);
procedure FormClose(Sender: TObject; var Action: TCloseAction);
procedure Timer1Timer(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;var
frmInitForms: TfrmInitForms;implementation{$R *.dfm}
uses udatamodule, comm2, uInitForms_thread, uInMainList;procedure TfrmInitForms.Timer1Timer(Sender: TObject);
begin
if pbInMainList.Position>=pbInMainList.Max then
begin
pbInMainList.Position:=0;
end
else
begin
pbInMainList.Position:=pbInMainList.Position + pbInMainList.Step;
end;
end;end.多线程类的代码如下:
unit uInitForms_Thread;interfaceuses
Classes, StdCtrls, ComCtrls, ExtCtrls, Graphics, ADODB, SysUtils, Forms;//Windows, , Forms;
type
InitForms_Thread = class(TThread)
private
procedure InitInMainList();
procedure InitOutMainList();
procedure InitInSearch();
procedure InitOutSearch();
procedure InitBillManage();
protected
public lblInMainList: TLabel;
LblInSearch: TLabel;
lblOutMainList: TLabel;
lblOutSearch: TLabel;
lblBillManage: TLabel;
pbInMainList: TProgressBar;
pbInSearch: TProgressBar;
pbOutMainList: TProgressBar;
pbOutSearch: TProgressBar;
pbBillManage: TProgressBar;
Timer1: TTimer;
constructor create;
procedure Execute; override;
end;implementationuses
uInitForms, udatamodule, comm2, uInMainList, uInSearch,
uOutMainList, uOutSearch, uBillManage;procedure InitForms_thread.Execute;
begin
timer1:=uInitForms.frmInitForms.Timer1; lblInMainList:=uInitForms.frmInitForms.lblInMainList;
pbInMainList:=uInitForms.frmInitForms.pbInMainList; lblInSearch:=uInitForms.frmInitForms.lblInSearch;
pbInSearch:=uInitForms.frmInitForms.pbInSearch; lblOutMainList:=uInitForms.frmInitForms.lblOutMainList;
pbOutMainList:=uInitForms.frmInitForms.pbOutMainList; lblOutSearch:=uInitForms.frmInitForms.lblOutSearch;
pbOutSearch:=uInitForms.frmInitForms.pbOutSearch; lblBillManage:=uInitForms.frmInitForms.lblBillManage;
pbBillManage:=uInitForms.frmInitForms.pbBillManage; pbInMainList.Position:=0;
pbInSearch.Position:=0;
pbOutMainList.Position:=0;
pbOutSearch.Position:=0;
pbBillManage.Position:=0; self.InitInMainList;
self.InitInSearch;
self.InitOutMainList;
self.InitOutSearch;
self.InitBillManage;
end;constructor InitForms_thread.create;
begin
FreeOnTerminate:=true;
inherited create(false);
end;procedure InitForms_thread.InitInMainList();
begin
lblInMainList.Font.Color:=clRed;
lblInMainList.Caption:='正在初始化当日收货信息列表';
timer1.Enabled:=true;
//开始创建窗体
if frmInMainList = nil then
begin
frmInMainList := TfrmInMainList.Create(Application );
end;
//创建窗体后,最小化窗体
frmInMainList.WindowState:=wsMinimized;
pbInMainList.Position:=pbInMainList.Max;
timer1.Enabled:=false;
lblInMainList.Font.Color:=clgreen;
lblInMainList.Caption:='当日收货信息列表初始化完成';
end;procedure InitForms_thread.InitInSearch();
begin
lblInSearch.Font.Color:=clRed;
lblInSearch.Caption:='正在初始化收货查询数据';
timer1.Enabled:=true;
//开始创建窗体
if frmInSearch = nil then
begin
frmInSearch := TfrmInSearch.Create(Application );
end;
//创建窗体后,最小化窗体
frmInSearch.WindowState:=wsMinimized;
pbInSearch.Position:=pbInSearch.Max;
timer1.Enabled:=false;
lblInSearch.Font.Color:=clgreen;
lblInSearch.Caption:='收货查询数据初始化完成';
end;procedure InitForms_thread.InitOutMainList();
begin
//红色字体提示
lblOutMainList.Font.Color:=clRed;
lblOutMainList.Caption:='正在初始化当日发货信息列表';
timer1.Enabled:=true;
//开始创建窗体
if frmOutMainList = nil then
begin
frmOutMainList := TfrmOutMainList.Create(Application );
end;
//创建窗体后,最小化窗体
frmOutMainList.WindowState:=wsMinimized;
//填满进度条
pbOutMainList.Position:=pbOutMainList.Max;
//停止进度条滚动
timer1.Enabled:=false;
//绿色字体提示
lblOutMainList.Font.Color:=clgreen;
lblOutMainList.Caption:='当日发货信息列表初始化完成';
end;procedure InitForms_thread.InitOutSearch();
begin
lblOutSearch.Font.Color:=clRed;
lblOutSearch.Caption:='正在初始化发货查询数据';
timer1.Enabled:=true;
//开始创建窗体
if frmOutSearch = nil then
begin
frmOutSearch := TfrmOutSearch.Create(Application );
end;
//创建窗体后,最小化窗体
frmOutSearch.WindowState:=wsMinimized;
pbOutSearch.Position:=pbOutSearch.Max;
timer1.Enabled:=false;
lblOutSearch.Font.Color:=clgreen;
lblOutSearch.Caption:='发货查询数据初始化完成';
end;procedure InitForms_thread.InitBillManage();
begin
lblBillManage.Font.Color:=clRed;
lblBillManage.Caption:='正在初始化单据管理数据';
timer1.Enabled:=true;
//开始创建窗体
if frmBillManage = nil then
begin
frmBillManage := TfrmBillManage.Create(Application );
end;
//创建窗体后,最小化窗体
frmBillManage.WindowState:=wsMinimized;
pbBillManage.Position:=pbBillManage.Max;
timer1.Enabled:=false;
lblBillManage.Font.Color:=clgreen;
lblBillManage.Caption:='单据管理数据初始化完成';
end;end.
主窗体代码如下:
unit uInitForms;interfaceuses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, ComCtrls, ExtCtrls, ADODB, Buttons;type
TfrmInitForms = class(TForm)
GroupBox1: TGroupBox;
lblInMainList: TLabel;
lblInSearch: TLabel;
lblOutMainList: TLabel;
lblBillManage: TLabel;
pbInMainList: TProgressBar;
pbInSearch: TProgressBar;
pbOutMainList: TProgressBar;
pbBillManage: TProgressBar;
Timer1: TTimer;
pbOutSearch: TProgressBar;
lblOutSearch: TLabel;
procedure Button1Click(Sender: TObject);
procedure btnUploadClick(Sender: TObject);
procedure FormDestroy(Sender: TObject);
procedure FormClose(Sender: TObject; var Action: TCloseAction);
procedure Timer1Timer(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;var
frmInitForms: TfrmInitForms;implementation{$R *.dfm}
uses udatamodule, comm2, uInitForms_thread, uInMainList;procedure TfrmInitForms.Timer1Timer(Sender: TObject);
begin
if pbInMainList.Position>=pbInMainList.Max then
begin
pbInMainList.Position:=0;
end
else
begin
pbInMainList.Position:=pbInMainList.Position + pbInMainList.Step;
end;
end;end.多线程类的代码如下:
unit uInitForms_Thread;interfaceuses
Classes, StdCtrls, ComCtrls, ExtCtrls, Graphics, ADODB, SysUtils, Forms;//Windows, , Forms;
type
InitForms_Thread = class(TThread)
private
procedure InitInMainList();
procedure InitOutMainList();
procedure InitInSearch();
procedure InitOutSearch();
procedure InitBillManage();
protected
public lblInMainList: TLabel;
LblInSearch: TLabel;
lblOutMainList: TLabel;
lblOutSearch: TLabel;
lblBillManage: TLabel;
pbInMainList: TProgressBar;
pbInSearch: TProgressBar;
pbOutMainList: TProgressBar;
pbOutSearch: TProgressBar;
pbBillManage: TProgressBar;
Timer1: TTimer;
constructor create;
procedure Execute; override;
end;implementationuses
uInitForms, udatamodule, comm2, uInMainList, uInSearch,
uOutMainList, uOutSearch, uBillManage;procedure InitForms_thread.Execute;
begin
timer1:=uInitForms.frmInitForms.Timer1; lblInMainList:=uInitForms.frmInitForms.lblInMainList;
pbInMainList:=uInitForms.frmInitForms.pbInMainList; lblInSearch:=uInitForms.frmInitForms.lblInSearch;
pbInSearch:=uInitForms.frmInitForms.pbInSearch; lblOutMainList:=uInitForms.frmInitForms.lblOutMainList;
pbOutMainList:=uInitForms.frmInitForms.pbOutMainList; lblOutSearch:=uInitForms.frmInitForms.lblOutSearch;
pbOutSearch:=uInitForms.frmInitForms.pbOutSearch; lblBillManage:=uInitForms.frmInitForms.lblBillManage;
pbBillManage:=uInitForms.frmInitForms.pbBillManage; pbInMainList.Position:=0;
pbInSearch.Position:=0;
pbOutMainList.Position:=0;
pbOutSearch.Position:=0;
pbBillManage.Position:=0; self.InitInMainList;
self.InitInSearch;
self.InitOutMainList;
self.InitOutSearch;
self.InitBillManage;
end;constructor InitForms_thread.create;
begin
FreeOnTerminate:=true;
inherited create(false);
end;procedure InitForms_thread.InitInMainList();
begin
lblInMainList.Font.Color:=clRed;
lblInMainList.Caption:='正在初始化当日收货信息列表';
timer1.Enabled:=true;
//开始创建窗体
if frmInMainList = nil then
begin
frmInMainList := TfrmInMainList.Create(Application );
end;
//创建窗体后,最小化窗体
frmInMainList.WindowState:=wsMinimized;
pbInMainList.Position:=pbInMainList.Max;
timer1.Enabled:=false;
lblInMainList.Font.Color:=clgreen;
lblInMainList.Caption:='当日收货信息列表初始化完成';
end;procedure InitForms_thread.InitInSearch();
begin
lblInSearch.Font.Color:=clRed;
lblInSearch.Caption:='正在初始化收货查询数据';
timer1.Enabled:=true;
//开始创建窗体
if frmInSearch = nil then
begin
frmInSearch := TfrmInSearch.Create(Application );
end;
//创建窗体后,最小化窗体
frmInSearch.WindowState:=wsMinimized;
pbInSearch.Position:=pbInSearch.Max;
timer1.Enabled:=false;
lblInSearch.Font.Color:=clgreen;
lblInSearch.Caption:='收货查询数据初始化完成';
end;procedure InitForms_thread.InitOutMainList();
begin
//红色字体提示
lblOutMainList.Font.Color:=clRed;
lblOutMainList.Caption:='正在初始化当日发货信息列表';
timer1.Enabled:=true;
//开始创建窗体
if frmOutMainList = nil then
begin
frmOutMainList := TfrmOutMainList.Create(Application );
end;
//创建窗体后,最小化窗体
frmOutMainList.WindowState:=wsMinimized;
//填满进度条
pbOutMainList.Position:=pbOutMainList.Max;
//停止进度条滚动
timer1.Enabled:=false;
//绿色字体提示
lblOutMainList.Font.Color:=clgreen;
lblOutMainList.Caption:='当日发货信息列表初始化完成';
end;procedure InitForms_thread.InitOutSearch();
begin
lblOutSearch.Font.Color:=clRed;
lblOutSearch.Caption:='正在初始化发货查询数据';
timer1.Enabled:=true;
//开始创建窗体
if frmOutSearch = nil then
begin
frmOutSearch := TfrmOutSearch.Create(Application );
end;
//创建窗体后,最小化窗体
frmOutSearch.WindowState:=wsMinimized;
pbOutSearch.Position:=pbOutSearch.Max;
timer1.Enabled:=false;
lblOutSearch.Font.Color:=clgreen;
lblOutSearch.Caption:='发货查询数据初始化完成';
end;procedure InitForms_thread.InitBillManage();
begin
lblBillManage.Font.Color:=clRed;
lblBillManage.Caption:='正在初始化单据管理数据';
timer1.Enabled:=true;
//开始创建窗体
if frmBillManage = nil then
begin
frmBillManage := TfrmBillManage.Create(Application );
end;
//创建窗体后,最小化窗体
frmBillManage.WindowState:=wsMinimized;
pbBillManage.Position:=pbBillManage.Max;
timer1.Enabled:=false;
lblBillManage.Font.Color:=clgreen;
lblBillManage.Caption:='单据管理数据初始化完成';
end;end.
//开始创建窗体
if frmInMainList = nil then
begin
frmInMainList := TfrmInMainList.Create(Application );
end;
//创建窗体后,最小化窗体
frmInMainList.WindowState:=wsMinimized;
替换成连接数据库等不涉及窗体的代码后,是可以正常运行的。不知为什么不能在多线程类中创建窗体
跟踪了一下代码,是canvas引起的,既不报错也不提示,直接就死机,郁闷啊!
建议你下来看一下。
写了个简单示例,你可以试一下。主要要用 Synchronize() 来进行线程 同步。当然了,也可以用sendmessage或者postMessage。Delphi5开发人员指南中都有。
unit Unit1;interfaceuses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;type
TForm1 = class(TForm)
btn1: TButton;
procedure btn1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;var
Form1: TForm1;implementationuses Unit2;{$R *.dfm}procedure TForm1.btn1Click(Sender: TObject);
var
a : aaa;
begin
a := aaa.Create(False);
end;end.unit Unit2;interfaceuses
Classes;type
aaa = class(TThread)
private
{ Private declarations }
protected
procedure Execute; override;
procedure ChildCreate;
end;implementation{ aaa }uses Unit3,Unit1;procedure aaa.ChildCreate;
begin
if not Assigned(Form3) then
Form3:= TForm3.Create(Form1);
Form3.Show;
end;procedure aaa.Execute;
begin
{ Place thread code here }
Synchronize(ChildCreate);
end;end.
线程中通过同步方法来实现更新。
Thanks, 我根据你的思路试试。
Thanks, 你的方法试过了,使用你的方法后,程序不再死机了,但在创建其他窗体的同时进度条也假死了,还是没有起到多线程的目的啊。
线程中通过同步方法来实现更新。
也就是说 你在Execute的方法里用同步方法,如(Synchronize()、sendmessage()、postmessage())对主线程中对象进行更新。
Thanks, 我的目的是在创建其他窗体的时候,让进度条滚动起来,使得界面友好些,使用 Synchronize(ChildCreate)后,虽然不死机了,但在创建其他窗体的时候,界面还是静止的。
你有什么较好的方法呢?
按上面的例子改了下。
procedure aaa.Execute;
begin
{ Place thread code here }
Synchronize(ChildCreate);
repeat
Synchronize(updateMMo);
sleep(1000);
until SizeOf(Form3.mmo1.Lines) > 1000;
end;procedure aaa.updateMMo;
begin
Form3.mmo1.Lines.Add('aabbbccc');
end;如果多个线程更新同一个进度条,则需要用到临界区 进行多线程 间的同步。具体的你可以查一下。
如,先在主窗体里 定义一个变量 cs : TRTLCriticalSection;
再在btn1点击时,初始化 InitializeCriticalSection(cs);
在线程 Execute;更新主线程对像方法中加上进临界区和出临界区
EnterCriticalSection(cs);
Synchronize(updateMMo);
LeaveCriticalSection(cs);
最后,别忘了关掉临界区。
DeleteCriticalSection(cs);
在做临界区更新时,一定要每个线程都要进行临界区保护。
Thanks,
你的方法试过了,还是不行啊,
Synchronize(ChildCreate);
执行完之后,才执行
repeat
Synchronize(updateMMo);
sleep(1000);
until SizeOf(Form3.mmo1.Lines) > 1000;所以还是,进度条还是静止的啊真郁闷
同时去掉线程里的Timer.
我觉得可以用beginthread来写创建过程可以灵活点
件也不可以。Type
TMyThread=class(TThread)
private
FMaxProgress:Integer;//进度的最大值
FProgress:Integer//当前的进度值
published
property MaxProgress:Integer read FMaxProgress;
property Progress:Integer read FProgress;
end;
在开始执行线程的时候将MaxProgres设置好,在执行的过程中修改 Progress 。
在界面上你放一个 TTimer控件,和5个进度条,每秒执行一次
procedure TForm1.OnTime(Sender:TObject)
begin
//这里读取每个线程的 MaxProgres 和 Progress 给进度条赋值。
end;
//你可以在另外放一个 TTimer tmr_show ,初始设置Enabled=false ,Interval=500;
//在窗体的
procedure TForm1.FormShow(Sender: TObject);
begin
tmr_show.Enabled:=True;
end;
procedure TForm1.tmr_showTimer(Sender: TObject);
begin
//在这里创建线程。
end;
我说一下我的问题,现在的程序的问题是,用户打开每个界面时速度较慢(共有五个界面),为了解决这个问题,我想在程序启动时,就先把这五个窗体加载上,然后把windowstate属性设为wsMinimized,这个当用户再次打开时,速度就比较快了。 在程序启动时,加载这五个窗体需要一段时间,现在想在用户等待这段时间的过程中,显示一个动画界面。但是这个动画界面总是无法实现。 该如何解决呢? 谢谢