1

現在、クライアント (IdTCPClient) とサーバー (IdTCPServer) の間で安定したコードがあり、すべて計画どおりに動作しています。ただし、ボタンの OnClick イベントから次の関数を呼び出すと、サーバーがフリーズします。

var
  SendStream: TMemoryStream;
  FileStream: TFileStream;
  List: TList;
  I: Integer;
begin
  try
    //Load
    FileStream := TFileStream.Create(Path, fmOpenRead);
    FileStream.Position := 0;
    //Place into stream
    SendStream := TMemoryStream.Create;
    SendStream.Write(Header, SizeOf(Header)); //This works; supporting code ommitted  for brevity
    SendStream.CopyFrom(FileStream, FileStream.Size);
    SendStream.Position := 0;

    TIdContext(fTCP.Contexts.LockList[0]).Connection.IOHandler.Write(SendStream, 0, True);
    fTCp.Contexts.LockList;
   if Assigned(Self.fServerOnSync) then Self.fServerOnSync(SizeOf(Header)) //event handler for main form

  finally
    FileStream.Free;
    SendStream.Free;
  end;

スレッドのデッドロックと関係があると推測していますが、私の人生では、なぜそれが発生しているのかわかりません。

また、カスタム fServerOnSync イベントを呼び出す IdTCP サーバーを含むクラスに上記のコードをカプセル化すると、これはスレッドセーフですか?

乾杯、 エイドリアン

4

1 に答える 1

1

fTCp.Contexts.LockList()2 回呼び出していますが、まったく呼び出していないfTCp.Contexts.UnlockList()ため、サーバーはContextsリストにアクセスしようとするたびにデッドロック状態になります。リストをロックした後、リストのロックを解除する必要があります。

var 
  SendStream: TMemoryStream; 
  FileStream: TFileStream; 
  List: TList; 
  I: Integer; 
begin 
  FileStream := TFileStream.Create(Path, fmOpenRead or fmShareDenyWrite); 
  try 
    SendStream := TMemoryStream.Create; 
    try
      SendStream.Write(Header, SizeOf(Header));
      SendStream.CopyFrom(FileStream, FileStream.Size); 
      SendStream.Position := 0; 

      List := fTCP.Contexts.LockList; 
      try
        TIdContext(List[0]).Connection.IOHandler.Write(SendStream, 0, True); 
      finally
        fTCP.Contexts.UnlockList; 
      end;
      if Assigned(fServerOnSync) then fServerOnSync(SizeOf(Header)); 
    finally 
      SendStream.Free; 
    end; 
  finally
    FileStream.Free; 
  end;
  ...
end;
于 2012-07-24T06:55:56.020 に答える