Delphi 显示异步';等等';窗
在Delphi VCL应用程序中,我想在执行耗时的过程时创建一个“等待”消息窗口(本例中是一个无用的大循环) 在我开始这个耗时的过程之前,我已经尝试过执行以下事情Delphi 显示异步';等等';窗,delphi,asynchronous,non-modal,Delphi,Asynchronous,Non Modal,在Delphi VCL应用程序中,我想在执行耗时的过程时创建一个“等待”消息窗口(本例中是一个无用的大循环) 在我开始这个耗时的过程之前,我已经尝试过执行以下事情 unit Unit1; interface uses Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs,
unit Unit1;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls,
popUpMessage;
type
TForm1 = class(TForm)
Button1: TButton;
Label1: TLabel;
procedure Button1Click(Sender: TObject);
end;
var
Form1: TForm1;
dialog : TForm;
implementation
{$R *.dfm}
procedure TForm1.Button1Click(Sender: TObject);
var i, j, k :LongInt;
begin
{1}
popUpMessage.Form2 := TForm2.Create(nil); //also tried with Create(self)
Form2.show;
{2}
dialog := CreateMessageDialog ('Wait',TMsgDlgType.mtWarning, mbYesNoCancel);
dialog.Show;
{3}
messagedlg('Wait',mtError, mbOKCancel, 0);
{4}
Label1.Caption := 'Wait';
//Time consuming process
for i := 0 to 200000 do
for j := 0 to 20000do
k := i-j;
end;
end.
-创建包含消息的简单窗口的新形式
-使用messagedlg创建消息
-甚至在主窗体上更改TLabel.Caption(执行耗时处理的窗体)
在{1}和{2}的情况下,弹出表单在耗时的过程开始之前出现,但只有在这一过程完成后,才会绘制其组件
案例{3}保持执行直到模式对话框关闭
在案例{4}中,标题在耗时的过程完成后更改
如何异步创建消息,以便在不等待其父进程的情况下完全绘制消息?这是一个有点宽泛的问题,因此我将提供一个简短的示例,演示如何将长时间运行的任务移动到线程,并安全地向UI提供进度和完成反馈 我不想麻烦第二个进度表单,在本例中,我只是在新的TForm中添加了一个按钮(Button1)和一个进度条(ProgressBar1) 在下面的方法中,我们启动一个匿名线程来执行长时间运行的操作,并定期以固定的进度间隔通知主线程。我们还将在工作完成时发出通知。为了扩展这一点,您还可以执行错误检查/处理,还可以在操作失败时发出通知,但为了简洁起见,我将示例限制为一些简单的内容
procedure TForm1.Button1Click(Sender: TObject);
begin
ProgressBar1.Position := 0;
Button1.Enabled := false;
Button1.Caption := 'Calculating...';
TThread.CreateAnonymousThread(
procedure
procedure PerformProgressStep;
begin
TThread.Queue(nil, procedure
begin
ProgressBar1.StepIt;
end);
end;
procedure NotifyComplete;
begin
TThread.Queue(nil, procedure
begin
ShowMessage('done');
Button1.Enabled := true;
Button1.Caption := 'Start Task';
end);
end;
var
i, j, k : integer;
begin
for i := 0 to 199999 do begin
for j := 0 to 20000 do k := i-j;
if (i mod 20000) = 0 then PerformProgressStep;
end;
NotifyComplete;
end).Start;
end;
在这里,所有UI操作都使用TThread.Queue
编组到主线程<如果在线程中继续操作之前必须等待主线程处理工作,则code>.Synchronize也是一个选项,但在这种情况下必须注意避免死锁情况
这段代码中没有任何错误处理,也要小心——这只是为了演示如何将工作转移到后台线程中。还有许多其他方法可以做到这一点,使用匿名线程(如上所述),如果要封装较重的实现,则使用自定义TThread,使用任务和RTL线程池,使用线程
单元中的并行循环操作,等等。您决定使用哪一种取决于您特定应用的要求
要更深入地了解Delphi中的多线程,您可以随时使用。这是一篇相当古老的文章,因此它在较低的层次上涉及多线程的主题,并使用了基本的RTL和WinAPI结构,并且不包括更现代版本的Delphi中包含的任何更新的语言特性。但是,这本书很有启发性,是复习基础知识的绝佳读物。这是一个有点宽泛的问题,因此我将提供一个简短的示例,演示如何将长时间运行的任务转移到线程,并安全地向UI提供进度和完成反馈 我不想麻烦第二个进度表单,在本例中,我只是在新的TForm中添加了一个按钮(Button1)和一个进度条(ProgressBar1) 在下面的方法中,我们启动一个匿名线程来执行长时间运行的操作,并定期以固定的进度间隔通知主线程。我们还将在工作完成时发出通知。为了扩展这一点,您还可以执行错误检查/处理,还可以在操作失败时发出通知,但为了简洁起见,我将示例限制为一些简单的内容
procedure TForm1.Button1Click(Sender: TObject);
begin
ProgressBar1.Position := 0;
Button1.Enabled := false;
Button1.Caption := 'Calculating...';
TThread.CreateAnonymousThread(
procedure
procedure PerformProgressStep;
begin
TThread.Queue(nil, procedure
begin
ProgressBar1.StepIt;
end);
end;
procedure NotifyComplete;
begin
TThread.Queue(nil, procedure
begin
ShowMessage('done');
Button1.Enabled := true;
Button1.Caption := 'Start Task';
end);
end;
var
i, j, k : integer;
begin
for i := 0 to 199999 do begin
for j := 0 to 20000 do k := i-j;
if (i mod 20000) = 0 then PerformProgressStep;
end;
NotifyComplete;
end).Start;
end;
在这里,所有UI操作都使用TThread.Queue
编组到主线程<如果在线程中继续操作之前必须等待主线程处理工作,则code>.Synchronize也是一个选项,但在这种情况下必须注意避免死锁情况
这段代码中没有任何错误处理,也要小心——这只是为了演示如何将工作转移到后台线程中。还有许多其他方法可以做到这一点,使用匿名线程(如上所述),如果要封装较重的实现,则使用自定义TThread,使用任务和RTL线程池,使用线程
单元中的并行循环操作,等等。您决定使用哪一种取决于您特定应用的要求
要更深入地了解Delphi中的多线程,您可以随时使用。这是一篇相当古老的文章,因此它在较低的层次上涉及多线程的主题,并使用了基本的RTL和WinAPI结构,并且不包括更现代版本的Delphi中包含的任何更新的语言特性。但是,这本书很有启发性,是一本很好的基础知识读物。你必须将耗时的过程放到一个单独的线程中。@nolaspeaker,这与将弹出窗口放到一个单独的线程中不一样吗?因为你可能很快也会被
ProcessMessages
的黑暗恶魔所诱惑,这里有一些额外的相关阅读:@Mikemik你不能把弹出窗口放在一个单独的线程上。在Delphi中,UI(用户界面)线程是“显示”的位置。这就是为什么你必须为其他的事情做一个单独的线程。而且你不应该做任何在线程中“显示”的事情。请参见下面J..的答案。您必须将耗时的进程放在一个单独的线程上。@nolaspeaker,这与将弹出窗口放在一个单独的线程中不一样吗?因为您可能很快也会被ProcessMessages
的黑暗恶魔所诱惑,这里有一些额外的相关阅读:@Mikemik你不能把弹出窗口放在一个单独的线程上。在Delphi中,UI(用户界面)线程是“显示”的位置。这就是为什么你必须离开我