恢复计算机后线程不会继续

时间:2016-05-27 10:25:48

标签: c# tcp

我使用TcpClient.BeginConnect连接到客户端,只要未请求CancellationToken取消,我就会运行一个循环。

while (!_token.IsCancellationRequested)
{
    var s = reader.ReadLine() ?? string.Empty;
}

我还通过记录重新连接和处理异常。

当我启动此应用程序时,一切都按预期工作。但是,当我让我的电脑进入睡眠状态并再次将其唤醒时,似乎所有线程都已终止。

工作流程如下:

  1. 我(从主线程)开始执行DoWork的新任务。我这样执行:Task.Run(()=>DoWork(),_token);
  2. DoWork实例化一个新TcpClient并启动BeginConnect,如下所示:
  3. (_client = new TcpClient()).BeginConnect(Address, Port, ConnectCallback, _client);

    1. ConnectCallback内我有一个 while 语句,该语句不断从流中读取数据(见上文)。
    2. 知道计算机进入睡眠状态时线程会发生什么?

2 个答案:

答案 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。