C#:Обработка сигнала завершения в потоке обработчика TCP?

StackOverflow https://stackoverflow.com/questions/1864236

Вопрос

Я использую класс TcpClient в C #.

Каждый раз, когда поступает новый запрос на tcp-соединение, обычной практикой является создание нового потока для его обработки.И у основного потока должна быть возможность завершить эти потоки обработчиков в любое время.

Мое решение для каждого из этих потоков обработчика выглядит следующим образом:

1 Check NetworkStream's DataAvailable method
    1.1 If new data available then read and process new data
    1.2 If end of stream then self terminate
2 Check for terminate signal from main thread
    2.1 If terminate signal activated then self terminate
3 Goto 1.

Проблема с таким подходом к опросу заключается в том, что все эти потоки обработчиков будут занимать значительные ресурсы процессора, особенно если таких потоков огромное количество.Это делает его крайне неэффективным.

Есть ли лучший способ сделать это?

Это было полезно?

Решение

Видишь Пример асинхронного серверного сокета чтобы узнать, как сделать это ".NET way", без создания новых потоков для каждого запроса.

Другие советы

Хотите верьте, хотите нет, но 1000-тиковый режим сна действительно обеспечит бесперебойную работу.

private readonly Queue<Socket> sockets = new Queue<Socket>();
private readonly object locker = new object();
private readonly TimeSpan sleepTimeSpan = new TimeSpan(1000);
private volatile Boolean terminate;

private void HandleRequests() 
{
    Socket socket = null;

    while (!terminate)
    {
        lock (locker)
        {
            socket = null;
            if (sockets.Count > 0)
            {
                socket = sockets.Dequeue();
            }
        }

        if (socket != null)
        {
            // process
        }

        Thread.Sleep(sleepTimeSpan);
    }   
}

Я помню, как работал над похожим сервисом Windows.Это был NTRIP-сервер, который может принимать около 1000 TCP-подключений и направлять данные в NTRIP-кастер.

Если у вас есть выделенный сервер для этого приложения, то это не будет проблемой, если вы не добавите больше кода в каждый поток (ввод-вывод файлов, базы данных и т.д. - Хотя в моем случае у меня также была обработка базы данных для входа / выхода для каждого соединения).

На что следует обратить внимание:

  1. Пропускная способность, когда потоки увеличиваются до 600 или около того.Вы начнете видеть отключения, когда окно буфера TCP по какой-либо причине будет заблокировано или доступная пропускная способность будет недостаточной
  2. Операционная система, в которой вы запускаете это приложение, может иметь некоторые ограничения, которые могут привести к отключениям

Вышесказанное может быть неприменимо в вашем случае, но я просто хотел, чтобы оно было размещено здесь, потому что я столкнулся с этим во время разработки.

Вы правы в том, что не хотите, чтобы все ваши потоки были "заняты ожиданием" (т.е.запускаем небольшой цикл снова и снова).Вы либо хотите, чтобы они блокировались, либо хотите использовать асинхронный ввод-вывод.

Как упоминал Джон Сондерс, асинхронный ввод-вывод - это "правильный способ" сделать это, поскольку он может масштабироваться до сотен подключений.По сути, вы вызываете BeginRead() и передаете ему функцию обратного вызова.Функция BeginRead() возвращается немедленно, и когда поступают данные, функция обратного вызова вызывается в потоке из пула потоков.Функция обратного вызова обрабатывает данные, снова вызывает BeginRead(), а затем возвращает, что возвращает поток обратно в пул.

Однако, если вы будете одновременно открывать только несколько подключений, вполне нормально создать поток для каждого соединения.Вместо того чтобы проверять свойство DataAvailable в цикле, продолжайте и вызовите Read().Поток будет блокироваться, не потребляя никакого процессора, до тех пор, пока данные не станут доступны для чтения.Если соединение потеряно или вы закрываете его из другого потока, вызов Read() вызовет исключение, которое вы можете обработать, завершив свой поток чтения.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top