结束程序Delphi

时间:2014-04-30 09:33:08

标签: delphi delphi-xe2

我有一个程序需要来自SQL-Server的数据,没有它就行不通(好吧,它可以但完全没用)。

按顺序有2种自动创建形式,DMOD和Main。

这是DMOD OnCreate中的代码:

  if not fileexists(UdlFile) then
  begin
    ITRCreateFile(UdlFile);
    ShellExecute(Application.Handle,'open',UdlFile,nil,nil,SW_SHOW);
     try
       cnConnect.Close;
       if gServerPort <> '' then
          cnConnect.connectionString:= 'Provider=SQLOLEDB.1;Password=*;Persist Security Info=True;User ID=itreflex;Initial Catalog=ExquisStudio;Data Source=' + gServerName + '\' + gServerPort + ';Use Procedure for Prepare=1;Auto Translate=True;Packet Size=4096;Workstation ID=' + gServerName + ';Use Encryption for Data=False;Tag with column collation when possible=False'
       else
          cnConnect.connectionString:= 'Provider=SQLOLEDB.1;Password=*;Persist Security Info=True;User ID=itreflex;Initial Catalog=ExquisStudio;Data Source=' + gServerName + ';Use Procedure for Prepare=1;Auto Translate=True;Packet Size=4096;Workstation ID=' + gServerName + ';Use Encryption for Data=False;Tag with column collation when possible=False';
       cnConnect.Open();
   except
      Showmessage('Problems with dataconnection - error SQL data');
      screen.Cursor := crDefault;
      Application.terminate;
   end;
  end
  else
  begin
     try
       cnConnect.Close;
       if gServerPort <> '' then
          cnConnect.connectionString:= 'Provider=SQLOLEDB.1;Password=*;Persist Security Info=True;User ID=itreflex;Initial Catalog=ExquisStudio;Data Source=' + gServerName + '\' + gServerPort + ';Use Procedure for Prepare=1;Auto Translate=True;Packet Size=4096;Workstation ID=' + gServerName + ';Use Encryption for Data=False;Tag with column collation when possible=False'
       else
          cnConnect.connectionString:= 'Provider=SQLOLEDB.1;Password=*;Persist Security Info=True;User ID=itreflex;Initial Catalog=ExquisStudio;Data Source=' + gServerName + ';Use Procedure for Prepare=1;Auto Translate=True;Packet Size=4096;Workstation ID=' + gServerName + ';Use Encryption for Data=False;Tag with column collation when possible=False';
        cnConnect.Open();
     except
       Showmessage('Problems with dataconnection - error SQL data');
       screen.Cursor := crDefault;
       Application.terminate;
     end;
  end;

问题是,程序关闭,没有任何东西是可见的,但是进程一直在运行,主要是95%或更高的CPU使用率。那不是很好......

我做了一些挖掘并找到Thread not terminated while application is terminated under Delphi

我在ExitProcess(0);之后添加了Application.terminate;,现在流程应该关闭了。我使用0因为参数是必需的,我不知道它应该是什么。

我的问题是:这样做可以吗?它做我想要的但我感觉我忽略了一些东西。

3 个答案:

答案 0 :(得分:2)

ExitProcess将结束您的流程。但是以牺牲任何适当的整理为代价。你真正应该做的是找出程序没有关闭的原因。运行什么是阻止关闭?无法从问题中的代码中辨别出该信息。你需要深入挖掘一下。

如果您无法使用静态分析,那么您可以使用调试器来帮助:

  1. 启动在调试器下运行的程序。
  2. 执行调用Application.Terminate
  3. 的操作
  4. 使用Run | Program Pause暂停执行。
  5. 使用View | Debug Windows | Threads查看线程的状态。
  6. 双击线程以选择它并查看其调用堆栈。
  7. 这些调用堆栈应该足以解决哪个线程忙,从而阻止程序终止。首先要看的是主线程。等什么呢?回答这个问题,你应该能够解决问题。

答案 1 :(得分:0)

好的,我想我找到了。

这就是我所做的:

  1. 我从自动创建表单列表中删除了Main,因此只有DMOD保留在那里。如果没有连接,我注意到程序真的挂在这里。

  2. 我在例外部分中删除了Application.terminate;

  3. 这是我之前发布的代码之下的代码。这也是在Exception-part中调用Application.terminate;后仍然执行的代码。我在这里添加了一个额外的支票,如果一切顺利的话,也可以在这里打电话给主。

    if cnConnect.Connected then
    begin
      ADOPermissions.Open;
      ADOGroupMembers.Open;
      ADOGroupAccess.Open;
      ADOGroups.Open;
      ADOUserAccess.Open;
      ADOUsers.Open;
      Application.CreateForm(TfrmMain, frmMain);
    end
    else
      Application.terminate;
    
  4. 现在这个过程就会消失。

  5. 我觉得有点愚蠢,我没有像现在这样使用断点来发现这一点,但我认为Application.terminate;会停止并直接杀死这个过程。

答案 2 :(得分:0)

您最初的问题是您在创建主表单之前尝试有序关闭程序。这通常是一个危险的过程,因为WM_QUIT消息的处理(终止发送的内容)可能会受到程序中所有类型的东西的不利影响,这些东西在您的终止调用和进入应用程序主消息循环之间发生。

我通常使用两种结构中的一种来管理这个

第一个选项是主表单在主表单初始化期间向数据模块询问其状态,并让主表单决定退出。

第二个选项是让主窗体创建数据模块而不是首先自动创建。这基本上是相似的,但确实意味着数据模块中的终止更有可能起作用。

任何一个选项都将终止代码放在主表单中,在Delphi运行时已经理解了需要发送关闭消息以启动关闭的主表单的标识之后放置它。