在我的C#项目中,我使用以下代码在自己的类之外访问我的表单。
public static FormMain singletonInstance { get; private set; }
public static void PFA(Action<FormMain> action) //PFA = PerForm Action
{
var form = FormMain.singletonInstance;
if (form != null)
{
form.PerformAction(action);
}
}
public void PerformAction(Action<FormMain> action)
{
if (InvokeRequired)
Invoke(action, this);
else
action(this);
}
“FormMain”中的构造函数是:
public FormMain()
{
InitializeComponent();
singletonInstance = this;
}
我不知道如何在Delphi中这样做。
问题(Delphi):当Im在其类之外时,如何更改表单上的内容(例如Edit1.Text),Invoke?
提前致谢!
答案 0 :(得分:8)
对 Invoke()操作的需要与调用代码在其类内部或外部无关,因此必须确保在控件上操作的方法仅在上下文中调用控件创建的线程。控件具有线程关联,这与C#或.NET无关,它是Windows工作方式中固有的。控件/窗口的消息只能在创建它的线程中处理。对于Delphi也是如此,整个VCL也不是线程安全的。
最接近 Invoke()的Delphi VCL是 Synchronize()方法。它在辅助线程中用于调度要在主VCL线程(需要创建所有VCL控件的用户界面线程)的上下文中执行的代码,因此处理这些控件的所有Windows消息,并且唯一一个真正安全地调用任何控制方法。
Delphi程序本身不会创建任何辅助线程,您必须自己完成。但除非你这样做,否则一切都发生在主线程上下文中,并且不需要调用 Synchronize()。您只需调用需要调用的方法即可。
继续您的示例:为编辑控件设置新文本,如下所示:
Form1.Edit1.Text := 'foo bar baz';
这假设包含TForm1
类的单元包含变量Form1
,它通常会这样做。这类似于C#代码中的单例。它的工作原理是因为删除到表单上的所有控件都具有公共可见性。
题外话-备注:
请注意,虽然这是相当常见的代码,但它违反了Law of Demeter。更改表单中的控件将使得有必要随后更改以这种方式访问它们的所有代码。但这完全是另一个讨论。