36697
StreamReaderのタイムアウトについて教えて下さい。  
以下のような形でStreamReaderに対してReadTimeoutの値を設定する  
ことによって１分でReadLine()を抜けてくれます。  
（例外：転送接続からデータを読み取れません: 接続済みの呼び出し先が  
一定の時間を過ぎても正しく応答しなかったため、接続できませんでした。）

ただし、それは最初の一回だけで、２回めのReadLine()に入った以降  
は直ぐに抜けて（タイムアウト値が効いていない）同じ例外が発生します。  
以下にプログラムの抜粋を示します。

```

    serverReader = new StreamReader(netStream, Encoding.UTF8);
    serverReader.BaseStream.ReadTimeout = 60000;      <=== １分でタイムアウトに設定
    
    // スレッド内の処理
    private bool ProcessMessage(StreamReader reader)
    {
        lock (this) {
            while (true) {
                try {
                    string message = reader.ReadLine();  ===> １回目は正しく１分でタイムアウトが発生する
                    if (message != null) {
                        ss = ParseMessage(message,this);
                    }
                }
                catch (Exception e) {
                    ===> １回目は正しく１分でタイムアウトが発生するのだが
                    ===> ２回目以降は直ぐにReadLine() から抜けてしまう
                    if (IsKill) {
                        result = false;
                        break;
                    }
                    Thread.Sleep(50);
                }
            }
        }
    }
    
```

質問は２回目以降もこのReadTimeout 値が効くようにするのはどの様に  
すれば良いのでしょうか？
CC BY-SA 3.0
2017-07-26T13:01:31.300
36696
2017-07-26T13:24:46.530
2017-07-26T13:24:46.530
21092
24591
question
c#
C#でのTCP/IP通信のReadTimeoutが２回目以降効かない
`NetworkStream`に限らず一般論としてTCP/IPはストリームです。読み出し途中で中断する場合、読み出せたデータを返す必要があり、逆に返さなければストリームが一部欠落してしまうことになります。その時点でTCP/IPストリームとして意味をなさなくなります。

さて`NetworkStream`では`ReadTimeout`プロパティでタイムアウトを設定した場合、例外を発生させる仕様であり、途中まで読み出せたデータを返す手段がありません。引き続き読み出しを行いたいのであれば別のアプローチをとる必要があります。

例えば、[`NetworkStream.Socket`](https://msdn.microsoft.com/ja-
jp/library/bk6w7hs8\(v=vs.100\).aspx)から[`Socket.Blocking`](https://msdn.microsoft.com/ja-
jp/library/system.net.sockets.socket.blocking\(v=vs.110\).aspx)を`false`に設定することで
**ノンブロッキングモード** を有効化します。ノンブロッキングモードでは読み出せるだけのデータを返し、受信待ちを行わなくなります。  
ただし、受信待ちを行わないためタイムアウト処理をAPIに任せることはできなくなりますので、呼び出し側で呼び出しタイミングを調整する必要がありますし、バッファリングを行う`StreamReader`を使用してしまうとこれまた呼び出しタイミングを制御できなくなってしまうため、`NetworkStream`もしくは`Socket`を直接操作する必要があります。
CC BY-SA 3.0
2017-07-26T13:24:21.673
36697
2017-07-26T13:24:21.673
4236
36696
answer