德尔福:应用程序初始化 - 最佳实践/方法

问题描述:

我经常遇到这个问题,并且正在寻找最佳实践/方法。我有一个包含数据库/数据模块的应用程序,并且希望在启动时启动数据库/数据集,而不必在设计时将“运行时激活”设置为true(数据库位置各不相同)。当应用程序启动时,还可以运行网络“检查更新”例程。德尔福:应用程序初始化 - 最佳实践/方法

鉴于TForm的事件序列,并从不同的试验和错误的结果,我目前使用这种方法:

我使用“全局”记录在主窗体来存储所有全局变量设置,有一个称为Globals.AppInitialized(boolean)的元素,并在主表单的初始化部分将其设置为False。

在主窗体的OnShow事件(所有窗体都是在那时创建的),我测试了Globals.AppInitialized;如果它是假的,我运行我的“初始化”的东西,然后通过设置Globals.AppInitialized:= True完成。

这似乎工作得很好,但它是最好的方法?寻找别人的经验,想法和意见。 TIA ..

+0

从10年前的视频:https://youtu.be/_PJdZjM2oTw覆盖这一点。 – Alister 2018-01-15 01:47:37

我一般总是关闭自动创建的所有形式除主要形式,可能主要数据模块。

我学会了你可以做的一个诀窍就是将你的数据模块添加到你的项目中,允许它自动创建并在你的主窗体之前创建。然后,当你的主窗体被创建时,datamodule的onCreate已经被运行。

如果您的应用程序有一些代码可以说,请设置控件的焦点(创建时不能执行的操作,因为它的“不可见”),然后创建用户消息并将其发布到您的表单中OnCreate中。消息SHOULD(不保证)会在处理表单消息循环后立即处理。例如:

const 
    wm_AppStarted = wm_User + 101; 


type 
    Form1 = class(tForm) 
    : 
    procedure wmAppStarted(var Msg:tMessage); message wm_AppStarted; 
    end; 

// in your oncreate event add the following, which should result in your wmAppStarted event firing. 
PostMessage(handle,wm_AppStarted,0,0); 

我想不出这是从来没有处理此消息的单一的时间,但通话的本质在于,它被添加到消息队列,如果队列已满则被“丢弃”。请注意存在边缘情况。

+3

+1提示禁用表单自动创建。这是Delphi应用程序启动速度慢的原因之一。另外Windows消息用于延迟处理值得关注。 – mghie 2008-12-20 16:06:12

+0

wmAppStarted过程的主体应该是什么? – Wojtas 2013-01-11 17:06:13

我不确定我明白你为什么需要全局变量?现在我编写所有我的Delphi应用程序,没有一个全局变量。即使当我使用它们时,我每次应用程序的数量也不会超过几个。

所以,也许你需要先想想为什么你真的需要它们。

+1

总的来说,我避开了它们,但在某些情况下,我发现有几个变量看起来好像属于“应用程序本身”。这是一个例子。有时我会在以另一种形式运行一些例程之前检查它。 也可以将它设置为表单或DM的“属性”。 – Jamo 2008-12-19 23:48:53

德尔福实际上并没有像“全局变量”这样的概念。所有变量的范围都与它们所在的单位以及使用该单位的其他单位有关。

只是使AppInitialized初始化东西作为您的数据模块的一部分。基本上有一个类(或数据模块),以排除所有非UI的东西

或者你可以(有点像一环,但不是所有的邪恶,这样的。):

  • 把它从你的闪屏。
  • 在登录期间执行此操作
  • 在后台线程中运行“检查更新” - 不要强制更新。它有点像Firefox一样。
+0

谢谢吉姆 - 很有帮助。要点也注意到:“全局变量”的区别。 定时明智的,你看到的任何问题瓦特/从主窗体的OnShow中的事件“炒”初始化的东西? (不过,我喜欢你在数据模块中容纳实际* code *的想法)。 – Jamo 2008-12-20 00:34:31

+0

OnShow中的问题在于,显示表单与您想要执行的操作无关。并非所有事情都需要在表单的情况下发生。 – 2008-12-20 01:02:39

+0

感谢您的输入,Rob! – Jamo 2009-03-28 00:57:49

您可能希望在表单创建调用之后和Application.Run之前直接干扰项目源(.dpr文件)。 (甚至更早的情况下)

这是怎么了,我通常处理这样的初始化的东西:

... 
Application.CreateForm(TMainForm, MainForm);  
... 
MainForm.ApplicationLoaded; // loads options, etc.. 
Application.Run; 
... 
+3

是的!知道“主表单”不是该程序的入口点并且OnShow不是表单的入口点很重要。 – 2008-12-20 00:59:41

我不知道这是有益的,但我的一些应用程序没有任何形式的自动生成的,即它们在IDE中没有的MainForm。

与应用对象创建作为其所有者将自动成为MainForm的第一种形式。因此,我只能自动创建一个datamodule作为加载程序,并让它决定创建何种数据模块以及以何种顺序创建哪些表单。这个datamodule有一个StartUp和ShutDown方法,在dpr的Application.Run周围被称为“括号”。 ShutDown方法可以对关闭过程进行更多的控制。

当你已经设计了不同的“mainforms”为您的应用程序的不同的使用情况,也可以使用一些配置文件来选择不同的mainforms这可能是有用的。

一招我用的是将一个TTimer主窗体上,时间设定为像300毫秒,并执行任何初始化(DB登录,网络文件副本等)。启动应用程序立即启动主窗体并允许任何初始化“事物”发生。用户无需启动多个实例思考“Oh..I没有DBL点击......我会再次这样做。”

我使用主数据模块,以检查是否DB连接正常,并如果没有,显示自定义组件的形式建立数据库连接,然后加载的主要形式有:

Application.CreateForm(TDmMain, DmMain); 

    if DmMain.isDBConnected then 
    begin 
     Application.CreateForm(TDmVisualUtils, DmVisualUtils); 
     Application.CreateForm(TfrmMain, frmMain); 
    end; 

    Application.Run;