Когда они простаивают более 5 минут, загрузка ЦП приложения увеличивается до 90% и остается там.
Для решения этой проблемы я встроил токен отмены, который срабатывает через 4 минуты.
Правильный ответ - решить проблему высокой загрузки ЦП.
Похоже, это здесь:
while (IsConnected)
{
try
{
var result = await SocketTaskExtensions.ReceiveAsync(ClientConnection.Client, buffer, SocketFlags.None);
if (result > 0)
{
...
}
}
catch ...
{
...
}
}
Сокеты странные, и правильно работать с необработанными сокетами TCP / IP. Кроме того, я всегда рекомендую разработчикам использовать что-то более стандартное, например HTTP или WebSockets, но в этом случае вы не контролируете клиентов, так что это не вариант.
В частности, ваш код не обрабатывает случай, когда result == 0
. Если клиентские устройства изящно закрыли свой сокет, вы увидите result
из 0
, сразу же вернетесь назад и продолжите получать result
из 0
- плотный цикл, который использует CPU.
Это, конечно, предполагается, что IsConnected
остается true
. И это может быть возможно ...
Вы не показываете, где IsConnected
установлено в вашем коде, но я подозреваю, что оно находится в обработке ошибок после отправки сообщения пульса. Вот почему это может работать не так, как ожидалось ... Я подозреваю, что клиентские устройства закрывают свой поток отправки (ваш поток приема), сохраняя при этом свой поток получения (ваш поток отправки) открытым. Это один из способов закрыть сокет, который иногда считается «более вежливым», поскольку он позволяет другой стороне продолжать отправку данных, даже если эта сторона закончила отправку. (Это с точки зрения клиентского устройства, поэтому «другая сторона» - это ваш код, а «эта сторона» - это клиентское устройство).
И это совершенно законно для сокетов, потому что каждый подключенный сокет - это два потока, а не один, каждый из которых может быть независимо закрыт. Если это произойдет, ваше сердцебиение все равно будет отправлено и получено без ошибок (и, вероятно, просто молча отброшено клиентским устройством), IsConnected
останется true
, и цикл чтения станет синхронным и поглотит ваш ЦП.
Чтобы решить эту проблему, добавьте проверку для result == 0
в цикле чтения и очистите клиент так же, как если бы сердцебиение не удалось отправить.