0

私はDelphiPrismを使用してMono用のソフトウェアを作成および構築しています。そこで、シリアル通信はスレッドで処理することにしました。プロジェクトのグローバル変数オプションを有効にしない限り、グローバル変数は厳密には許可されないため、DelphiPrismの規則に従うことにしました。では、どのようにしてパブリック変数またはフィールドをスレッドに渡したり、アクセス可能にしたりしますか?

これが私のテストメインフォームコードです:

MainForm = partial class(System.Windows.Forms.Form)

  private
    method SignalBtn_Click(sender: System.Object; e: System.EventArgs);
    method CommBtn_Click(sender: System.Object; e: System.EventArgs);
    method button1_Click(sender: System.Object; e: System.EventArgs);
    method button2_Click(sender: System.Object; e: System.EventArgs);
    method button4_Click(sender: System.Object; e: System.EventArgs);
    method button5_Click(sender: System.Object; e: System.EventArgs);
    method MainForm_Load(sender: System.Object; e: System.EventArgs); 
    method ShutdownBtn_Click(sender: System.Object; e: System.EventArgs);
    method MySerialData(sender: System.Object; e:SerialDataReceivedEventArgs);
    method LoginBtn_Click(sender: System.Object; e: System.EventArgs);
  protected
    method Dispose(disposing: Boolean); override;
  public
    RX:Array[0..5] of byte;
    TX:Array[0..6] of byte;
    serialPort1:System.IO.Ports.SerialPort;
    thr:Thread;
    stoploop:Boolean;
    mcommand:Byte;
    thechannel:Integer;
    constructor;
    method FillTable;
  end;

シリアル通信のスレッドは次のとおりです。

  ThreadComm = class(MainForm)
  public
    class procedure mythread; static;
  end;

ThreadCommの実行方法は次のとおりです。

class procedure ThreadComm.mythread;
begin
    while true do
    begin
        TX[0]:=$FF;
        TX[1]:=$01;
        TX[2]:=$01;
        TX[3]:=$04;
        TX[4]:=$A2;
        TX[5]:=(TX[2] xor TX[3] xor TX[4]);

        SerialPort1.Write(TX,0,6);
        while SerialPort1.BytesToWrite>0 do;
        Thread.Sleep(100);

        if (stoploop) then
            break;
    end;
end;

コードをコンパイルするたびに、次のような30個程度の同様のエラーメッセージが表示されます。

インスタンス参照なしでインスタンスメンバー「SerialPort1」を呼び出すことはできません

エラーの意味はわかっていますが、それを解決する唯一の方法は、メインフォームのインスタンスを作成することです。これを行うと、メインプログラムのインスタンスと同じインスタンスにはなりません。この場合、フィールドまたはパブリック変数にアクセスする必要があるときは、常にmainformの新しいインスタンスを作成する必要があります。右?

class method Program.Main(args: array of string);
begin
  Application.EnableVisualStyles();
  Application.SetCompatibleTextRenderingDefault(false);
  Application.ThreadException += OnThreadException;
  **using lMainForm := new MainForm do
    Application.Run(lMainForm);**
end;

それらすべてを使用したいのですが、変数はスレッド内にあり、たまたまメインフォームのパブリックエリア内にあります。

ありがとう

4

2 に答える 2

1

スレッドが必要とするものをパラメーターとしてコンストラクターに渡します。これらのオブジェクトへの参照をスレッドクラスのフィールドとして保存します。スレッドの実行中にそれらを使用します。

また、スレッドクラスをメインフォームの子孫にしないでください。それは意味がありません。スレッドがフォーム全体にアクセスする必要がある場合はMainForm、スレッドのコンストラクターへの参照を渡します。ただし、スレッドに必要なのがシリアルポートオブジェクトだけの場合は、フォーム全体ではなく、それを渡すだけです。

の追加のインスタンスを作成しないでくださいMainForm。これにより、より多くのフォームが作成されます。実際のメインフォームのフィールド値にアクセスすることはできません。

于 2011-07-12T13:39:24.433 に答える
1

スレッドプロシージャ(class procedure mythread; static;)は「静的」または「クラス」のようですが、アクセスするフィールドはMainFormインスタンスの通常のフィールドです。は1つしかないため、これは機能しませんが、procedure mythreadのインスタンスが複数存在する可能性がありますMainForm。実際には、のインスタンスはおそらく1つだけですがMainForm、コンパイラはそれを認識していません。

classそのプロシージャからプレフィックスとサフィックスの両方を削除staticして、インスタンスフィールドを読み取ることができる通常のインスタンスプロシージャにすることから始める必要があります。MainFormから派生したため、それでも十分ではありません。新しいインスタンスを作成しThreadComてスレッドを開始すると仮定します。メソッドを通常のインスタンスメソッドにすると、コードはコンパイルされますが、結果は得られません。MainFormののインスタンスのメンバーにアクセスするため、期待するものになります。

ソリューション:

  • プロシージャmythreadをのインスタンスメソッドにしますMainForm。すべての必須フィールドにアクセスし、適切なインスタンスからそれらにアクセスします。
  • Robの提案に従ってください。派生ではなく、新しいクラスを作成し、コンストラクターでMainFormそのインスタンスを渡しMainFormます。これは、スレッドプロシージャからのインスタンスです。MainFormの1つのインスタンスにリンクできないため、静的/クラスフィールドとプロシージャは(再び)避ける必要があります。
于 2011-07-12T13:52:12.933 に答える