1

正常に動作する次のコードを置き換えようとしています

TcpClient oC = new TcpClient(ip, port);
oC = new TcpClient(ip, port);
StreamReader messageReader;

try {
   messageReader = new StreamReader(oC.GetStream(), Encoding.ASCII);
   reply = messageReader.ReadLine();
}

try {
   using (messageReader = new StreamReader(oC.GetStream(), Encoding.ASCII))
   {
       reply = messageReader.ReadLine();
   }
}

しかし、私はInvalidOperationExceptionことわざを取得します

接続されていないソケットでの操作は許可されていません。

何が問題で、どうすれば修正できますか?

詳細:私はこのコードの前にoc.Connectを持っているので、接続されています。初めて使用したいときは正常に動作します。その後、その例外が発生します。少し遊んで、今私は得る:

破棄されたオブジェクトにアクセスできません。\r\nオブジェクト名: 'System.Net.Sockets.Socket'。

4

6 に答える 6

12

StreamReader を作成する前に、oc.Connect を呼び出してみてください。ソケットが接続されるまで、実際に読み取るものは何もないため、例外が発生します。

于 2009-02-25T15:45:29.540 に答える
4

Jaredsの回答に対する私のコメントを繰り返します。

アリ コメント:

この前に oc.Connect があり、1 回目は問題なく動作しますが、2 回目には「破棄されたオブジェクトにアクセスできません。\r\nオブジェクト名: 'System.Net.Sockets.Socket'.」も表示されます。– アリ (13 分前)

私はコメントしました:

「これは、StreamReader がストリームの所有権を取得し、開始したストリームを閉じて破棄するためです。この例では、TcpClient の NetworkStream です。ここで StreamReader を破棄する必要はありません」

于 2009-02-25T18:58:52.307 に答える
2

したがって、正しいコンストラクターを使用してください。

using (messageReader = 
        new StreamReader(oC.GetStream(), Encoding.ASCII, false, 4096, true))
{
   reply = messageReader.ReadLine();
}

最後のパラメータに注目し、 docsleaveOpen:でそれが何を意味するかを読んでください。

ただし、IIRC の StreamReader はストリームからコンテンツをバッファリングするため (デフォルトでは 4096 バイトの読み取り)、 StreamReader を破棄すると、ストリームの位置がデータの終わりを超えて進んでいることに驚くかもしれません。 StreamReader で読み取ります。StreamReader が所有権を取得できるようにすることは、通常は常に良い考えです。すべてのデータを読み取るまで、開いたままにできませんか?

于 2014-08-13T17:08:51.093 に答える
1

Jared に耳を傾けてください。あなたの実際の例外です。本当のエラーは、読み取りを試みる前に実際にソケットを接続したことがないことです。

編集:

一度接続すると、接続が切断されるか、オブジェクトがスコープを失うということが起こっているように聞こえます。この場合、おそらく切断をトラップし、最初にサーバーへの接続に使用されたソケットを再作成する必要があります。そのソケットが破棄されるとすぐに、同じ参照を再度使用することはできません。新しい参照をインスタンス化して使用する必要があります。

接続の範囲と使用状況を示す、より完全な例を投稿して、基になるソケットが GC によって取得されている場所を正確に確認できますか?

于 2009-02-25T15:47:10.190 に答える
1

また、messageReader を StreamWriter として宣言しました。StreamReader ではないでしょうか。

StreamWriter messageReader;

【OPで修正】

別のヒントとして、オブジェクトを渡すのではなく、using ステートメントでインスタンス化することをお勧めします。例外の実際の原因ではない可能性がありますが、MSDN から:

リソース オブジェクトをインスタンス化してから、変数を using ステートメントに渡すことができますが、これはベスト プラクティスではありません。この場合、制御が using ブロックを離れた後もオブジェクトはスコープ内に残りますが、おそらくアンマネージ リソースにアクセスできなくなります。つまり、完全に初期化されなくなります。using ブロックの外側でオブジェクトを使用しようとすると、例外がスローされる危険があります。このため、通常は using ステートメントでオブジェクトをインスタンス化し、そのスコープを using ブロックに限定することをお勧めします。

于 2009-02-25T15:48:15.167 に答える
-3

最初に StreamWriter を定義してから、それを「using」で使用することは許可されていないと思います。

これを試して:

TcpClient oC = new TcpClient(ip, port);
oC = new TcpClient(ip, port);

try {
   using (StreamWriter messageReader = new StreamReader(oC.GetStream(), Encoding.ASCII))
   {
       reply = messageReader.ReadLine();
   }
}
于 2009-02-25T15:47:35.870 に答える