2009-06-27 1 views
0

В моем проекте C# я использовал следующий код для доступа к моей форме за пределами своего собственного класса.Что такое эквивалент Delphi для вызова C# в форме (как вызвать в Delphi)?

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): Как мне что-то изменить в форме (например, Edit1.Text), когда Im вне своего класса, Invoke?

Заранее благодарен!

ответ

8

Необходимость в Invoke() действие не имеет ничего общего с вызывающим кодом внутри или вне его класса, необходимо убедиться, что методы, работающие с элементами управления, вызываются только в контексте потока управления был создан в. Элементы управления имеют сходство потоков, которое ничем не отличается от C# или .NET, оно присуще способу работы Windows. Сообщения для элемента управления/окна могут обрабатываться только в потоке, который он был создан. Это справедливо и для Delphi, и весь VCL также не является потокобезопасным.

Ближе всего к Invoke() делфийской VCL есть это метод Synchronize(). Он используется во вторичных потоках для планирования кода, который должен выполняться в контексте основного потока VCL, потока пользовательского интерфейса, в котором должны быть созданы все элементы управления VCL, в результате чего обрабатываются все сообщения Windows для этих элементов управления и которые единственный, действительно безопасный для вызова любого из методов управления.

Программа Delphi не создает никаких дополнительных потоков сама по себе, вам придется делать это самостоятельно. Но если вы этого не сделаете, все происходит в контексте основного потока, и нет необходимости звонить Синхронизировать(). Вы можете просто вызвать метод, который вам нужно вызвать.

Чтобы остаться с вашим примером: Вы можете установить новый текст для элемента управления редактированием, например, так:

Form1.Edit1.Text := 'foo bar baz'; 

Это предполагает, что блок, содержащий TForm1 класса содержит переменную Form1, что он обычно делает. Это похоже на синглтон в коде C#. Это работает, потому что все элементы управления, упавшие на форму, будут иметь общую видимость.

Оффтопик-замечание:

Обратите внимание, что в то время как это довольно общий код это нарушает Law of Demeter. Изменение элементов управления в форме потребует впоследствии изменить весь код, который обращается к ним таким образом. Но это еще одно обсуждение.