OK per fare l'elaborazione pesante nel callback asincroni?
-
09-10-2019 - |
Domanda
E 'OK per fare l'elaborazione pesante in callback asincroni di NET, li monopolizzavano per più secondi prima di tornare? O sto privando il sistema operativo / il tempo di esecuzione delle risorse importanti?
Per esempio, consideriamo TcpListener.BeginAcceptSocket
. Il mio callback inizia invocando EndAcceptSocket
, poi spende un po 'la ricezione dei dati, e solo allora si chiude il socket e ritorna. È così che è stato concepito per essere utilizzato, o sono mi aspettavo di fare l'elaborazione aggiuntiva per conto mio filo?
Soluzione
Sì, questo è il modo Sockets asincroni (client TCP, ascoltatori, ecc) sono progettati per l'uso. Si dovrebbe sempre assicurarsi che si richiama il metodo fine aysnc e poi fare tutto ciò elaborazione voi desiderate. Non invocando l'EndAccept (), EndSEnd (), EndReceive (), ecc, ecc metodi foglie potenzialmente aperta a una perdita di memoria, quindi è sempre una buona pratica da seguire.
I fili che vengono utilizzati non sono diversi che se avessi spooling manualmente un thread in background te stesso, e sono infatti disegnate per essere usato anche per "operazioni a lungo termine" di un paio di secondi. Fidati di me, non si vuole qualcosa che prende molto tempo per essere in esecuzione su un invio o un thread GUI.
Ho più di 90 sistemi basati mobili che utilizzano Sockets asincrono per commucation a un server e si fa un lavoro eccellente: molto più veloce di servizi web (ricordate tutti i protocolli web corrono sulla cima di una presa in ogni caso), facile da rilevare gli errori, ecc, ecc.
io faccio lo stesso sul mio codice Server (mescolato con qualche altro WCF per middleware e di comunicazione backend pezzi) ed è il comm più scalabile che abbiamo usato. Dovrete fare un Google su di esso, ma c'è un ragazzo che ha pubblicato il suo Test con questa tecnologia e fu in grado di supportare 1.000 comunicazioni simultanee a un server con appena 11 thread. Non male.
esempio Server da MS: http://msdn.microsoft.com/en -us / library / fx6588te.aspx
esempio client da MS: http://msdn.microsoft.com/en -us / library / bew39x2a.aspx
Ci vuole più di questi per farlo "perfezionato", ma questo è un buon posto per cominciare.
Altri suggerimenti
I ripetuto gli esperimenti di un articolo CodeProject su questo argomento e ha trovato la risultati per .NET 4 per essere simile a quello che sono stati descritti nel 2003. si noti che l'articolo non ha effettivamente elencare i risultati per la sezione problematica, ma se ho capito bene il problema principale esiste ancora.
I riutilizzato il codice da questo articolo CodeProject -. Basta scaricarlo per eseguire questo controllo direttamente o per sperimentare
Il test tenterà di usare 10 thread paralleli per contare alto come si può in 1 secondo.
Utilizzo di 10 thread in background (cioè new Thread()
)
T0 = 4451756 T1 = 4215159 T2 = 5449189 T3 = 6244135 T4 = 3297895 T5 = 5302370 T6 = 5256763 T7 = 3779166 T8 = 6309599 T9 = 6236041 Total = 50542073
Utilizzo di 10 elementi di lavoro ThreadPool
T0 = 23335890 T1 = 20998989 T2 = 22920781 T3 = 9802624 T4 = 0 T5 = 0 T6 = 0 T7 = 0 T8 = 0 T9 = 0 Total = 77058284
Si noti che solo gli elementi 4 filo lavoro piscina di 10 mai effettivamente eseguiti durante l'intervallo di tempo 1 s! Ciò è su una CPU quad-core, in modo che era un thread per core. Gli altri compiti eseguiti dopo i primi quattro completato e perché l'uno secondo assegnato era già scaduto, non hanno incrementano i loro contatori.
La conclusione qui: con compiti lunghi, ThreadPool farà alcuni compiti attendono dietro ad altri Quindi, vi consiglio vivamente contro di fare qualsiasi lunga elaborazione in compiti ThreadPool (come ad esempio i gestori di completamento asincroni)!. In caso contrario, si potrebbe tenere più importanti chiamate asincrone da completare se il trattamento dei dati sta intasando il CPU, o si potrebbe avere prestazioni molto instabile se solo alcune operazioni fanno molto di elaborazione.
Utilizzo di implementazione ThreadPool personalizzato da un articolo
T0 = 7175934 T1 = 6983639 T2 = 5306292 T3 = 5078502 T4 = 3279956 T5 = 8116320 T6 = 3262403 T7 = 7678457 T8 = 8946761 T9 = 8500619 Total = 64328883