0

私の 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): フォームの何か (Edit1.Text など) を、そのクラスの Invoke の外にあるときに変更するにはどうすればよいですか?

前もって感謝します!

4

1 に答える 1

8

アクションをInvoke()する必要性は、そのクラスの内部または外部にある呼び出しコードとは関係ありません。コントロールで動作するメソッドが、コントロールが作成されたスレッドのコンテキストでのみ呼び出されることを確認する必要があります。スレッド アフィニティは、C# や .NET に固有のものではなく、Windows の動作に固有のものです。コントロール/ウィンドウのメッセージは、それが作成されたスレッドでのみ処理できます。これは Delphi にも当てはまり、VCL 全体もスレッドセーフではありません。

Delphi VCL のInvoke()に最も近いのはSynchronize()メソッドです。メイン VCL スレッド、すべての VCL コントロールを作成する必要があるユーザー インターフェイス スレッドのコンテキストで実行されるコードをスケジュールするためにセカンダリ スレッド内で使用されます。その結果、これらのコントロールのすべての Windows メッセージが処理されます。制御メソッドを呼び出すのに本当に安全な唯一のものです。

Delphi プログラムは、独自に二次スレッドを作成しないため、自分で作成する必要があります。ただし、そうしない限り、すべてがメインスレッドのコンテキストで発生し、 Synchronize()を呼び出す必要はありません。呼び出す必要があるメソッドを呼び出すだけです。

あなたの例にとどまるには:編集コントロールの新しいテキストを次のように設定します:

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

TForm1これは、クラスを含むユニットに変数が含まれていることを前提としていますForm1が、通常はそうです。これは、C# コードのシングルトンに似ています。フォームにドロップされたすべてのコントロールが公開されているため、機能します。

オフトピックの発言:

これはかなり一般的なコードですが、デメテルの法則に違反していることに注意してください。フォーム内のコントロールを変更すると、この方法でそれらにアクセスするすべてのコードを後で変更する必要があります。しかし、これはまったく別の議論です。

于 2009-06-27T17:44:00.393 に答える