2010-11-20 3 views
1

Я разрабатываю TCP-сервер в .NET C#. Он использует асинхронный ввод-вывод (ввод-вывод) для обработки большого количества клиентов одновременно. Сейчас у меня есть все TCP-соединения в списке, которые я просматриваю постоянно, ища изменения в конечной машине какого-либо конкретного соединения. Конечный автомат для данного соединения обновляется после завершения ввода/вывода определенных флагов.C# .NET Server опроса нескольких подключений - есть ли лучший способ?

Я уверен, что есть лучший способ сделать это - текущая реализация очень интенсивно обрабатывается процессором, так как я не блокирую ожидание обновления, а скорее опроса без дросселирования. Мне все равно, работает ли мой сервер в цикле, но я предполагаю, что это плохой дизайн. Я пытаюсь найти способ обработки конкретного соединения только тогда, когда сигналы завершения ввода-вывода есть что-то, что нужно обработать, и ждать (т. Е. Спать), когда нет. Может ли кто-нибудь предложить хороший способ сделать это?

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

Все, что вы можете предложить, было бы высоко оценено!

Здесь (упрощенный) цикл, который выполняется в главном потоке (rgClient список клиентов):

//Do communications on each client we currently have connected. 
//This loops runs backwards so we can delete elements on the fly 
//without have to iterate through more than once. 
lock (rgClient) 
{ 
    for (i = rgClient.Count - 1; i >= 0; i--) 
    { 
     if (!rgClient[i].DoComm()) 
     { 
      rgClient[i].DoClose(); 
      rgClient.RemoveAt(i); 
     } 
    } 
} 

DoComm() выполняет обновление на конечный автомат для соединения, который включает в себя выполняя действия текущего состояния, а затем при необходимости перейдя в новое состояние. Вот это состояние класс для отправки простого пакета «Ack»:

class StateAck : State 
{ 
    public StateAck(TextBox txtOutputExt, Form fmOwner) 
     : base(txtOutputExt, fmOwner) 
    { 
     fWriting = false; 
    } 

    public override bool DoExecute(out Type tpNextState) 
    { 
     PktAck pkt; 

     if (!base.DoExecute(out tpNextState)) 
     { 
      return false; 
     } 

     //Start a write if we haven't yet 
     if (!fWriting) 
     { 
      pkt = new PktAck(); 
      fWriting = true; 

      return FPutPkt(pkt.rgbSerialize()); 
     } 

     //Is the read finished/has an error occurred? 
     if (fDataErrorWrite) 
     { 
      return false; 
     } 

     //Process the data 
     if (fDataWritten) 
     { 
      tpNextState = typeof(StateIdle); 
     } 

     return true; 
    } 

    private bool fWriting; 
} 

Исполнения проходит через DoExecute() каждый раз, когда DoComm() вызывается из главного потока. В 99% случаев ничего не происходит. Когда запись (которая инициируется вызовом FPutPkt()) завершена, флаг будет сигнализировать об этом, а затем следующее состояние будет установлено на «холостой». Я хочу, чтобы основной поток проверял только те клиенты, которые завершили свою сетевую активность и что-то нужно для обновления, чтобы избежать постоянных и избыточных проходов через DoExecute().

+2

Я бы предложил вам указать ваш код. Таким образом, у нас есть основа для обсуждения. –

+0

И почему эта процедура обработки ввода-вывода не может обрабатываться? Разве это не все, что нужно для завершения ввода-вывода? –

+0

вы можете проверить эту статью http://www.codeproject.com/KB/IP/dotnettcp.aspx – Iraklis

ответ

0

Я нашел решение, которое работает очень хорошо. Используйте EventWaitHandler (System.Threading) с автоматическим сбросом до WaitOne() в нижней части каждого прохода через цикл. Затем любой обратный вызов или вторичный поток может сигнализировать EventWaitHandler, вызывая EWH.Set(), что позволит циклу сделать другой проход. Отличный способ исключить использование процессора циклом опроса без существенных изменений в потоке программы. Надеюсь, это поможет кому-то.