1

このコードを使用して、サーバーへの接続を処理し、クライアントからデータを読み取ります

using(var client = _listener.EndAcceptTcpClient(ar))
{
        var clientStream = client.GetStream();
        // Get the request message 
        Messages.ReceiveMessage(clientStream, msg => ProcessRequest(msg, clientStream));
}

これで、パラメーターとして渡されたストリームで ReceiveMessage メソッドが呼び出さBeginRead()れますが、ObjectDisposedException が発生します。

Stream が不要になったときに stream.Dispose() を呼び出すことが解決策であることはわかっていますが、using句の使用を維持できる解決策を本当に探しています。

ありがとう

4

2 に答える 2

3

ここには 2 つの可能性があります。

まず、この非同期プロセスを実行して完了するまでブロックすることで、using ステートメントを保持できます。これは、 Ben M here によって提案されたアプローチです。

または、using ステートメントを削除して、クライアント変数を自分で破棄することもできます。これは、コンパイラの構文を使用するよりも面倒に思えるかもしれませんが、この状況で現在利用しようとしている非同期動作を維持できるという利点があり、ブロックの必要性がなくなります。ただし、これには変数を保存し、適切な場所に自分で破棄する必要があります (おそらくデリゲートの最後ですが、デリゲートが呼び出されない場合に備えて、後で確認する必要があります)。

C# の "using" ステートメントは優れていますが、適切でない状況があり、これはその 1 つかもしれません (非同期動作を保持する必要がある場合)。

于 2009-07-20T19:08:21.860 に答える
2

あなたはこれを行うことができます:

using (var client = _listener.EndAcceptTcpClient(ar))
{
    var clientStream = client.GetStream();

    using (var eh = new ManualResetEvent(false))
    {
        // Get the request message 
        Messages.ReceiveMessage(clientStream, msg =>
            {
                ProcessRequest(msg, clientStream);
                eh.Set();
            });

        eh.WaitOne();
    }
}

1 つの注意点: ManualResetEvent を再利用できるように適切な場所 (クラス インスタンス) に格納する場合は、再利用できるようにしてください。

また、投稿で説明した動作から、ReceiveMessage() は非同期操作であると想定していることにも注意してください。

于 2009-07-20T18:50:51.973 に答える