Domanda

Sto usando la classe TcpClient in C #.

Ogni volta che c'è una nuova richiesta di connessione TCP, la prassi è quella di creare un nuovo filo di gestirlo. E dovrebbe essere possibile per il thread principale per terminare questi fili di gestore in qualsiasi momento.

La mia soluzione per ognuno di essi filo conduttore è la seguente:

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.

Il problema di questo approccio di polling è che tutte queste discussioni gestore viene prendendo le risorse del processore significative e soprattutto così se c'è un numero enorme di questi fili. Questo lo rende altamente inefficiente.

C'è un modo migliore di fare questo?

È stato utile?

Soluzione

asincrono Server Socket Esempio per imparare a fare questo la "via NET", senza creare nuovi thread per ogni richiesta.

Altri suggerimenti

Che ci crediate o no che il sonno 1000 tick sarà davvero mantenere le cose in esecuzione liscia.

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);
    }   
}

Mi ricordo di lavorare su un simile tipo di servizio Windows. E 'stato un server NTRIP che può prendere circa 1000 connessioni TCP e percorso i dati ad un Caster NTRIP.

Se si dispone di un server dedicato per questa applicazione, allora non sarà un problema a meno che non si aggiungono più codice per ogni thread (File IO, ecc Database - anche se nel mio caso ho avuto anche l'elaborazione del database per registrare il in / out per ogni connessione).

Le cose da guardare fuori per:

  1. Bandwidth quando i fili va fino a 600 o così. Si inizierà a vedere disconnessioni quando la finestra TCP buffer è soffocato per una ragione o per l'ampiezza di banda disponibile è inferiore
  2. Il sistema operativo su cui è in esecuzione questa applicazione potrebbe avere alcune restrizioni, che possono causare disconnessioni

È possibile che questo potrebbe non essere applicabile nel vostro caso, ma ho solo voluto metterlo qui perché ho affrontato poi durante lo sviluppo.

Hai ragione che non si desidera che tutti i thread "occupato attesa" (vale a dire l'esecuzione di un piccolo anello più e più volte). O si desidera che il blocco, o se si desidera utilizzare I / O asincrono.

Come detto John Saunders, I / O asincrono è il "modo giusto" per fare questo, dal momento che può scalare fino a centinaia di connessioni. In sostanza, si chiama BeginRead () e passare una funzione di callback. BeginRead () restituisce immediatamente, e quando arrivano i dati, la funzione di callback viene richiamato su un thread dal pool thread. La funzione di callback elabora i dati, le chiamate BeginRead () di nuovo, e poi ritorna, che rilascia il filo di nuovo in piscina.

Tuttavia, se sarete possesso solo una manciata di connessioni aperte in un momento, è perfettamente bene per creare un thread per ogni connessione. Invece di controllare la proprietà DataAvailable in un ciclo, andare avanti e chiamare Read (). Il filo si bloccano, consumando senza CPU, fino a quando i dati sono disponibili per la lettura. Se la connessione viene persa, o si chiude da un altro thread, il () chiamata Leggi sarà un'eccezione, che è possibile gestire terminando il tuo thread di lettura.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top