2011-08-05 8 views
1

既知の問題があります。IdTCPServerは、非アクティブ化しようとしている間にハングします。私はそのような問題に関する記事をたくさん読んでおり、私はデッドロックが起こっていることに気付いています。しかし、問題の原因となるコードを正確に理解することは難しいです。私のアプリにはウィンドウがないので、VCLコンポーネントへの同期呼び出しが理由ではありません。 2つのイベントハンドラOnConnectとOnExecuteを取得しました。問題はOnConnectに表示されます。コードは:
別のTIdTCPServerのデッドロック状況

TMyServer = class 
... 
private 
FServer: TIdTCPServer; 
... 
end; 

TMyServer.ServerConnect(AContext...); //onconnect 
begin 
    try 
    if not Condition then 
    begin 
     ... 
     AContext.Connection.Disconnect; 
     Stop; 
    end 
    else Start; 
    except 
    on E: Exception do 
     if E is EIdException then raise; 
     ... 
    end; 

TMyServer.Start; 
begin 
    ... 
    FServer.active := true; 
    FServer.StartListening; 
    ... 
end; 

TMyServer.Stop; 
begin 
    ... 
    FServer.StopListening; 
    FServer.Active := false; 
    ... 
end; 

TMyServer.ServerExecute(AContext...); //onexecute 
begin 
    LLine := AContext.Connection.IOHandler.ReadLn; 
    case (LLine) of 
    ... 
    end; 
end; 

ServerExecuteのコードは非常に巨大であるので、私はそれをここに投稿しないでしょう。それに問題はないと思う。
クライアントがサーバーに接続し、条件がfalseの場合、サーバーはこのクライアントの接続を切断し、回線でハングアップしますFServer.Active := false;
私は既にコードからすべてのログを除外しました。ログファイル)。したがって、イベントハンドラには計算だけがあり、デッドロックの原因となるものはありません。 Indy例外の再発生について読んだことがありますが、それは私にも役立ちませんでした。
私はこの状況の目的を完全には理解していないと思うので、助けと説明を感謝します。

答えて

2

イベントハンドラのいずれかからサーバーを無効にしようとしています。そのため、コードがデッドロックしています。

ActiveプロパティをFalseに設定すると、実行中のクライアントスレッドはすべて終了し、スレッドが完全に終了するのを待ちます。 OnConnectOnDisconnect、およびOnExecuteイベントは、これらのスレッドのコンテキストでトリガされます。だから、自分自身とデッドロックを待っているスレッドで終わります。

サーバーが安全に自分自身を無効にさせるには、あなたは、例えば、TIdNotifyクラスを使用することなどによって、非同期的にそれを行う必要がありますが:

uses 
    ..., IdSync; 

TMyServer.ServerConnect(AContext...); //onconnect 
begin 
    try 
    if not Condition then 
    begin 
     ... 
     AContext.Connection.Disconnect; 
     TIdNotify.NotifyMethod(Stop); 
    end 
    else 
     TIdNotify.NotifyMethod(Start); 
    except 
    on E: Exception do 
     if E is EIdException then raise; 
     ... 
    end; 
end; 

ところで、あなたは手動でStartListening()StopListening()メソッドを呼び出す必要はありません。 Activeプロパティ設定ツールは内部的にそれを行います。

+0

ありがとうレミー。あなたは答えが私のためにすべてを明確にしました。 – gator88

関連する問題