Удаление TcpClient при наличии ссылки на NetworkStream

Скажем, у меня есть следующий код:

public static Client Connect(string hostname, int port, bool useSsl)
{
    TcpClient tcpClient = new TcpClient(hostname, port);
    if (!useSsl)
    {
        return new Client(tcpClient.GetStream());
    }
    SslStream sslStream = new SslStream(tcpClient.GetStream());
    sslStream.AuthenticateAsClient(hostname);
    return new Client(sslStream);
}

Когда я компилирую это, анализ кода говорит мне, что я должен удалить tcpClient до того, как ссылка выйдет за рамки. Проблема в том, что мне нужно дальше использовать базовый экземпляр потока, и я не могу распоряжаться здесь tcpClient. В то же время я не хочу хранить где-то ссылку на tcpClient, чтобы потом избавиться от нее, так как мне нужен только поток. Какое здесь правильное решение? Спасибо.


person eigenein    schedule 06.01.2012    source источник
comment
в чем проблема с сохранением ссылки на tcpClient ?   -  person Yahia    schedule 07.01.2012
comment
теперь вы хотите вернуть SSLStream или Client, если это так, измените возврат в моем примере и подпись метода..   -  person MethodMan    schedule 07.01.2012
comment
@Yahia Должно быть много экземпляров Client. Однако классу Client нужен экземпляр Stream только в качестве параметра, и я хочу оставить его независимым от класса TcpClient.   -  person eigenein    schedule 07.01.2012
comment
вопрос, когда вы возвращаете новый клиент (sslStream), является ли он нулевым или у вас есть ожидаемый поток.. если у него есть ожидаемый поток, то просто обнулите tcpClient перед обратным вызовом.. пожалуйста, уточните..   -  person MethodMan    schedule 07.01.2012
comment
Возможно, измените метод Connect со статического метода на метод экземпляра (или даже на конструктор), а затем сделайте ваш объект TcpClient частью класса Client.   -  person Matthew    schedule 07.01.2012
comment
@DJKRAZE Я исправил вопрос. Как я сказал ниже, проблема заключается в необходимости использовать базовый поток, в то время как tcpClient должен быть удален.   -  person eigenein    schedule 07.01.2012
comment
Посмотрите также на замечания Мэтью. Я тоже об этом думал, но иногда люди, которые задают вопросы, не хотят менять сигнатуры методов, но у него есть веская точка зрения.. +1   -  person MethodMan    schedule 07.01.2012
comment
@Matthew Я понимаю этот обходной путь, но хорошо ли ссылаться на класс TcpClient, в то время как Client нужен только Stream?   -  person eigenein    schedule 07.01.2012
comment
если вам нужен только поток, не возвращайте новый клиент (sslStream), просто верните поток и измените свой метод, чтобы разрешить общедоступный статический поток SSLStream Connect (string hostname, int port, bool useSsl)   -  person MethodMan    schedule 07.01.2012
comment
Насколько я знаю, если вы избавитесь от TcpClient, это сделает поток недействительным. Если вы используете только поток и не сохраняете объект TcpClient, то он будет просто принят GAC, и вы не сможете самостоятельно контролировать удаление. Объект в любом случае будет в памяти.   -  person Matthew    schedule 07.01.2012
comment
@Matthew Итак, вывод таков: просто оставьте мой код как есть?   -  person eigenein    schedule 07.01.2012
comment
Вероятно, это будет работать большую часть времени, однако, поскольку вы сказали, что создаете много соединений, было бы лучше явно закрыть соединения, когда они больше не работают.   -  person Matthew    schedule 07.01.2012
comment
@ Мэтью Хорошо. Пожалуйста, опубликуйте это как ответ, чтобы я мог принять его.   -  person eigenein    schedule 07.01.2012


Ответы (1)


вы можете сделать это двумя способами: 1. передать переменную по ссылке или 2. объявить приватную переменную вверху как SslStream sslStream = null; есть это

SslStream sslStream = new SslStream(tcpClient.GetStream()); 

измените его или метод, чтобы он читался следующим образом.

public static SSLStream Connect(ref string hostname, ref int port, bool useSsl) 
{     
   TcpClient tcpClient = new TcpClient(hostname, port);
   if (!useSsl) 
   {
      return new Client(tcpClient.GetStream());
   }
   sslStream = new SslStream(tcpClient.GetStream()); // or the ref sslStream 
   sslStream.AuthenticateAsClient(hostname);
   tcpClient = null; or if implements IDisposable then do this
   if (tcpClient != null)
   {
      ((IDisposable)tcpClient).Dispose();
   }
   return sslStream; //if yo
} 
person MethodMan    schedule 06.01.2012
comment
Конкретно с SslStream проблем нет. Проблема в том, что tcpClient должен быть удален, а базовый поток - нет. - person eigenein; 07.01.2012
comment
да, но когда вы избавляетесь от tcpClient, вы возвращаете SSLStream, теперь GAC может включиться, возможно, после того, как эта переменная sslStream выйдет за рамки, но, судя по всему, я предполагаю, что вы используете этот sslStream после обратного вызова .. делает это имеет смысл..? - person MethodMan; 07.01.2012