1

いくつかの特定のニーズのために、dll でソケット要求 (または応答) を待機するプロシージャを作成する必要があります。

TForm1 = class(TForm)
  ServerSocket1: TServerSocket;

......

procedure MyWaitProc; stdcall;
begin
  Go := false;
  while not Go do
  begin
    // Wating...
    // Application.ProcessMessages;     // Works with this line
  end;
end;


procedure TForm1.ServerSocket1ClientRead(Sender: TObject;
  Socket: TCustomWinSocket);
begin
  MessageBoxA(0, PAnsiChar('Received: '+Socket.ReceiveText), '', MB_OK);
  Go := true;
end;

exports
  MyWaitProc;

私が呼び出すとApplication.ProcessMessages、すべてが正常に機能します。アプリケーションはリクエストを待ってから続行します。しかし、私の場合、呼び出すApplication.ProcessMessagesと、ホスト アプリケーション (dll のものではない) のメイン フォームのロックが解除されます。アプリケーションを呼び出さないとApplication.ProcessMessages、メッセージを処理できないため、ハングアップします...

では、ソケットの回答を待っているようなプロシージャを作成するにはどうすればよいでしょうか? を使用せずにソケットの応答を待つ方法はありますApplication.ProcessMessagesか?

編集

TIdTCPServer も使用しようとしましたが、何らかの理由で結果は同じです。

TForm1 = class(TForm)
  IdTCPServer1: TIdTCPServer;
.....

procedure MyWaitProc; stdcall;
begin
  Go := false;
  while not Go do
  begin
    // Waiting ...
    // Application.ProcessMessages;
  end;
end;

procedure TForm1.IdTCPServer1Execute(AContext: TIdContext);
var
  s: string;
begin
  s := AContext.Connection.Socket.ReadString(1);
  AllText := AllText + s;
  Go := True;
end;
4

2 に答える 2

4

TServerSocketデフォルトでは非ブロッキングモードで実行されます。これはウィンドウメッセージの処理に依存します。その依存関係を削除するには、代わりにブロッキングモードに切り替える必要があります。

TIdTCPServer排他的にブロッキングモードで実行されるため、ウィンドウメッセージはありません。あなたがそれに問題を抱えているならば、あなたはそれを誤用しています。たとえば、コードでは、応答が受信されるまでTServerSocket設定しませんが、コードでは、代わりに応答を読み取る前に設定します。Go = TrueTServerSocketGo = True

別の方法として、IndyのTIdSimpleServerコンポーネントを見てください。 TIdSimpleServerは同期であり、一度に1つの接続のみを受け入れますが、TIdTCPServer非同期であり、一度に多くの接続を受け入れます。例えば:

TForm1 = class(TForm) 
  ServerSocket: TIdSimpleServer; 

procedure MyWaitProc; stdcall; 
var
  s: String;
begin 
  ServerSocket.Listen;
  s := ServerSocket.IOHandler.ReadLn;
  ServerSocket.Disconnect;
  MessageBox(0, PChar('Received: '+s), '', MB_OK); 
end; 

exports 
  MyWaitProc; 
于 2012-07-02T19:57:11.973 に答える
1

時々呼び出すループを作成するのではなくApplication.ProcessMessages、子孫を作成しTThreadてソケット要求をTThread.Executeメソッドに移動できます。TThread.OnTerminate を使用して、スレッドが作業を完了したときにフォーム (または他のクラス) に通知します。

使用方法の詳細を示すサンプル コードがありますTThread

マルチスレッドに慣れていない場合は、他のサードパーティのスレッド ライブラリよりも柔軟性が高いか、使いやすいものがいくつかあります。TThreadTThread

注:を使用すると、重大な副作用がいくつかありますApplication.ProcessMessages。アプリケーションのメインフォームのロックを解除するdllを使用して、コード内にそれらの1つが表示されています。VCL が構築されているシングルスレッドの UI モデルを壊します。 ProcessMessagesその場所はありますが、説明している状況にはスレッドを使用する方が適切です。

var Slowpoke: TMyLongRunningProcessThread;

procedure MyWaitProc(Completed:TNotifyEvent)
begin
  Slowpoke := TMyLongRunningProcessThread.Create(True);
  Slowpoke.FreeOnTerminate := True;
  Slowpoke.OnTerminate := Completed;
  Slowpoke.Resume;
end;

MyWaitProcスレッドの開始直後に戻るため、GUI はユーザーのアクションに自由に応答できます。スレッドが終了すると、 が指すイベント ハンドラが呼び出されCompletedます。

明らかに、スレッドからデータを取得する必要がある場合は、スレッドがそれ自体を解放する前にアクセス可能なメモリの場所に書き込むかFreeOnTerminate、プロパティを介してスレッドからデータを取得できるようにスレッドを削除する必要があります。

于 2012-07-02T13:51:51.830 に答える