Как закрыть клиент соединение сокета в объекте после того как он потерялся в куче?

Такой вот вопрос. У меня есть класс, допустим, Device. Этот класс предоставляет функционал взаимодействия с IoT-устройством("умная" вещь) и реализует его API. Каждый экземпляр этого класса представляет отдельное устройство. Удаленное устройство имеет два режима:

1) когда оно сервер - ограниченный режим, плохой режим, но устройство к нему автоматически переходит при выключении или перехвате его другим приложением.

2) когда оно клиент. То что мне нужно. Но приходится ловить соединения. И вот тут проблема.

Мой класс Device имеет статический Socket Server, который (после отправки "прямого" запроса устройству на подключение) делает Accept() в его экземпляре Device и инициализирует его поле Socket Client.

А вот и сама проблема. У меня есть класс Discoverer который в другом потоке каждые 5 сек. возвращает ссылку на новую коллекцию обнаруженных устройств. Старая коллекция уходит в небытие, а до Dispose() в котором я убиваю соединение, видимо, дело не доходит пока сборщик мусора не проснется. Таким образом при создании коллекции новых Device каждые 5 сек. я имею у них Socket Client == null, а соединения, видимо, открыты, т. к. следующий Accept() приводит программу в ступор.

Я могу, конечно, обновлять коллекцию выборочно, не создавая новую и сохраняя актуальные экземпляры Device, будучи уверенным что отвалившиеся устройства точно отсоеденены. Но ведь это решение проблемы извне. И это не reusable по отношению к слассу Device. Можно ли решить этот вопрос внутри Device? Ведь иначе могут всплыть внезапные ситуации в будущем. Код для наглядности:

В Discoverer создается коллекция

    FoundDevices = DiscoverDevices(); //Создается коллекция обнаруженных устройств
    if(CheckDevicesOnlineChanged())   //Сравнивает коллекции. Косячный метод(всегда true) помог увидеть проблему
    {
        DeviceCollectionChenged?.Invoke(FoundDevices); //классу-подписчику возвращается новая коллекция
    }

В Device каждый раз при создании

    private Socket Client = null;

При каждой отправке команды устройству форсится TCP подключение (2-й режим устройства)

    private void SendCommand(string command)
    {
        lock (CommandLocker)
        {
            byte[] comandBuffer = Encoding.UTF8.GetBytes(command);
            {
                try
                {
                    Client.Send(comandBuffer); //попытка не пытка
                }
                catch (Exception)
                {
                    Connect(); //пересоединим обратно 
                    Client.Send(comandBuffer); //попробуем снова
                }
            }
        }
    }

И тут на Accept() приходит осознание, что поциент скорее жив, чем мертв. Он просто чем-то занят.

    public void Connect()
    {

        if (Client == null) // а он каждые 5 сек. "null", т.к. объект все время создется заново
        {
            SendRequestForConnection(); //просим устройство к нам подключится
            Client = TcpServer.Accept(); //Ждем тепловой смерти вселенной при повторном вызове
        }
        IsConnected = true;

    }

Я уже не знаю что писать в Dispose(). Он, видимо, просто не вызывается. Удаленное устройство должно отключаться само при разрыве соединения. Если бы это вызывалось, проблем бы не было.

    public void Dispose()
    {
        Client.Close();
        Client.Dispose();
    }

Ответы (0 шт):