Есть 2 предложения, которые я бы сделал, учитывая код, и я предполагаю, что это ваш дизайн. Однако сначала я хотел бы отметить, что при работе с сетями ввода-вывода, такими как сеть или файловые системы, вы должны использовать неблокирующие обратные вызовы ввода-вывода. Это намного FAR более эффективно, и ваше приложение будет работать намного лучше, хотя их сложнее программировать. Я кратко расскажу о предлагаемой модификации дизайна в конце.
- Использовать использование () {} для TcpClient
- Thread.Abort ()
- TcpListener.Pending ()
- Асинхронное переписывание
Использовать использование () {} для TcpClient
*** Обратите внимание, что вы действительно должны заключить свой вызов TcpClient в блок using () {}, чтобы гарантировать, что методы TcpClient.Dispose () или TcpClient.Close () вызываются даже в случае исключения. Вы также можете поместить это в блок finally блока try {} finally {}.
Thread.Abort ()
Есть 2 вещи, которые я вижу, ты мог бы сделать. Во-первых, если вы запустили этот поток TcpListener из другого потока, вы можете просто вызвать метод потока Thread.Abort в потоке, который вызовет исключение threadabortexception в вызове блокировки и поднимется по стеку.
TcpListener.Pending ()
Вторым исправлением низкой стоимости будет использование метода listener.Pending () для реализации модели опроса. Затем вы должны использовать Thread.Sleep, чтобы «подождать», прежде чем посмотреть, ожидает ли новое соединение. Если у вас есть ожидающее соединение, вы вызываете AcceptTcpClient, и это освобождает ожидающее соединение. Код будет выглядеть примерно так:
while (listen){
// Step 0: Client connection
if (!listener.Pending())
{
Thread.Sleep(500); // choose a number (in milliseconds) that makes sense
continue; // skip to next iteration of loop
}
TcpClient client = listener.AcceptTcpClient();
Thread clientThread = new Thread(new ParameterizedThreadStart(HandleConnection));
clientThread.Start(client.GetStream());
client.Close();
}
Асинхронное переписывание
Наконец, я бы порекомендовал вам действительно перейти к неблокирующей методологии для вашего приложения. Под прикрытием платформа будет использовать перекрывающиеся порты ввода-вывода и завершения ввода-вывода для реализации неблокирующего ввода-вывода из ваших асинхронных вызовов. Это тоже не очень сложно, просто нужно немного подумать о вашем коде.
Обычно вы начинаете свой код с метода BeginAcceptTcpClient и отслеживаете возвращаемый вами IAsyncResult. Вы указываете на метод, который отвечает за получение TcpClient и передачу его NOT в новый поток, но в поток из ThreadPool.QueueUserWorkerItem, чтобы вы не раскручивали и не закрывали новый поток для каждый клиентский запрос (обратите внимание, что вам может понадобиться использовать свой собственный пул потоков, если у вас особенно долгоживущие запросы, потому что пул потоков используется совместно, и если вы монополизируете все потоки, другие части вашего приложения, реализованные системой, могут оказаться неэффективными). Как только метод слушателя запускает ваш новый TcpClient для его собственного запроса ThreadPool, он снова вызывает BeginAcceptTcpClient и направляет делегата обратно на себя.
Фактически вы просто разбиваете свой текущий метод на 3 различных метода, которые затем будут вызываться различными частями. 1. загрузить все, 2. стать целью для вызова EndAcceptTcpClient, запустить TcpClient в свой собственный поток и затем вызвать себя снова, 3. обработать запрос клиента и закрыть его, когда закончите.