1

私は使用しようとしています

private TcpClient tcpClient;

クラスでLISTRETRSTOR、 のようなコマンドを送信するたびに、コマンドを実行して応答を取得する特定の時間だけ TCPClient をロックしていました。

実行中に他のコマンドを送信すると、その tcpclient インスタンスを再度ロックできません。

実行中に他のコマンドを送信するにはどうすればよいですか。すべてのコマンドで、変更できない TCPClient をロックする必要があります。

4

3 に答える 3

2

これは設計上の問題です。過度にロックせずに TcpClient にアクセスするマルチスレッドの方法を設計する必要があります

TcpClient をロックする代わりにキューを使用することをお勧めしますか? あなたは FTP クライアントを構築しようとしていると思います。(LIST、RETR、および STOR コマンドに基づいて推測しています)。

単純なキューの例

private TcpClient client;
private Queue<string> commands = new Queue<string>();
private AutoResetEvent resume = new AutoResetEvent(false);

public void Add(string cmd)
{
  lock(commands) { commands.Enqueue(cmd); }
  resume.Set();

}

private void ThreadRun() // this method runs on a different thread
{
   while(!quit.WaitOne(0,true))
   {
      resume.WaitOne();
      string command;
      lock(commands) { command = commands.Dequeue(); }
      Process(command);

   }


}

スレッドセーフにするためだけにオブジェクトを「ロック」しようとするのは控えるべきです。スレッド セーフなアプリケーションは、ロックを強制してスレッド セーフを強制するのではなく、最小限のロックで動作するように設計されています。

于 2009-12-19T08:29:36.507 に答える
0

スレッドごとに1つのTcpClientを使用します。

于 2009-12-19T13:24:05.173 に答える
0

初めに。ソケットプログラミングに関して言えば、ロックはすべて悪いことです。@AndrewKeithのソリューションは、コマンドのキューイングと送信に非常に適しています。

必要なのは、別のキューに入れて応答とともに送り返すことができる要求 ID を持っていることです。そうすることで、いくつかの進行中のコマンドを持つことができます。

簡単な擬似コード:

public void Send(ICommand command)
{
    var myPacket = new CommandPacket {
        Command = command,
        RequestId = Guid.NewGuid()
    };
    _pendingCommands.Add(myPacket);

    var buffer = Serialize(myPacket);
    socket.Send(buffer);
}

public void OnReceive(IAsynResult ar)
{
    var bytesRead =  socket.EndRecieve(ar);
    _inStream.Write(_readBuffer, 0, bytesRead);

    if (GotCompletedPacket(_inStream))
    {
        var packet = Deserialize(_inStream);
        var waitingCommand = _pendingCommands.FirstOrDefault(p => p.RequestId == packet.RequestId);

        if (waitingCommand != null)
          //got a reply to the command.
    }

}

コマンドを呼び出すときに、個人的にデリゲートを追加します。

public void Send(ICommand command, ICommandHandler handler)

応答が受信されたときにそのハンドラーを呼び出します。

于 2012-02-03T20:40:18.793 に答える