Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/delphi/8.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Delphi 显示异步';等等';窗_Delphi_Asynchronous_Non Modal - Fatal编程技术网

Delphi 显示异步';等等';窗

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,

在Delphi VCL应用程序中,我想在执行耗时的过程时创建一个“等待”消息窗口(本例中是一个无用的大循环)

在我开始这个耗时的过程之前,我已经尝试过执行以下事情

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(用户界面)线程是“显示”的位置。这就是为什么你必须离开我