我使用TcpClient.BeginConnect
连接到客户端,只要未请求CancellationToken
取消,我就会运行一个循环。
while (!_token.IsCancellationRequested)
{
var s = reader.ReadLine() ?? string.Empty;
}
我还通过记录重新连接和处理异常。
当我启动此应用程序时,一切都按预期工作。但是,当我让我的电脑进入睡眠状态并再次将其唤醒时,似乎所有线程都已终止。
工作流程如下:
DoWork
的新任务。我这样执行:Task.Run(()=>DoWork(),_token);
DoWork
实例化一个新TcpClient
并启动BeginConnect
,如下所示: (_client = new TcpClient()).BeginConnect(Address, Port, ConnectCallback, _client);
ConnectCallback
内我有一个 while 语句,该语句不断从流中读取数据(见上文)。知道计算机进入睡眠状态时线程会发生什么?
答案 0 :(得分:0)
当您的计算机从睡眠状态唤醒时,有时(但不总是)会切断连接。这取决于许多因素,其中一些可能不在您的控制之下。
就回调方法而言,没有触发异常,但是当连接结束并且已读取所有先前数据时,reader.EndOfStream
将为真。 编辑:但是,如果TCP堆栈不知道远程已断开连接,则此调用将阻塞,直到数据到达,TcpClient.ReceiveTimeout
周期已过,或者直到TCP会话空闲超时为止,以此为准首先发生。
(编辑:如果没有数据发送,只有当TCP堆栈知道(基于其自身的网络状态检测或TCP数据包)远程断开连接时,连接才会自动结束;否则它将等到会话空闲超时,这可能需要长达一个小时左右,具体取决于客户端。一个解决方案是客户端定期发送数据(如果它最近没有收到数据)作为一种早期断线检测。)
事实上,当连接结束时(例如,在您的计算机唤醒之后),您发布的while
循环将进入紧密循环,最大化CPU核心,因为reader.ReadLine()
不断返回{{ 1}}。您可以检查并突破循环:
null
答案 1 :(得分:0)
这个问题的解决方案(虽然不是很好)是使用一个定时器,它在给定的时间后显式关闭连接。
double([],[]).
double([I|R],[I,I|RD]) :-
double(R,RD).
在访问流之前,我激活了这个计时器:
var timeoutTimer = new Timer(state =>
{
var temp = (TcpClient)state;
Log.Error("Read timeout. Closing connection.");
temp.Close();
}, client, Timeout.Infinite, Timeout.Infinite);
然后重置:
timeoutTimer.Change(20000, Timeout.Infinite); // Handle timeouts.
使用reader.EndOfStream或reader.ReadLine都会导致线程在该点停止,除非强制终止连接,否则不会解决该问题。
修改强> 设置TcpClient.ReceiveTimeout与上面做的一样 - 可能更好。当接收方在指定的时间内没有收到任何数据时(以毫秒为单位),则抛出IOException。