Prendere in considerazione il metodo Socket.BeginSend()
. Se due thread del pool di thread dovessero chiamare questo metodo simultaneamente, i loro rispettivi messaggi finiranno per mischiarsi tra loro o la classe socket impedirà che ciò accada?Le scritture asincrone su un thread socket sono sicure?
risposta
Ho trovato un sorriso post on the MSDN forum che sembra rispondere alla tua domanda.
- È possibile mettere in coda più BeginSends allo stesso tempo. Non è necessario bloccare
Edit:
informazioni ancora più interessante:
Se si scorre verso il basso un po 'nel Remark section of the MSDN doc BeginSend(), troverete uso interessante di callback metodi che potrebbero essere rilevanti per te.
[...] Se si desidera bloccare il thread originale dopo aver chiamato il metodo BeginSend, utilizzare il metodo WaitHandle.WaitOne. [...]
Non lo sapevo, grazie! – covertCoder
Questo è esattamente quello che stavo cercando! GRAZIE! – Dabloons
.NET Le istanze di socket non sono thread-safe in quanto le chiamate simultanee ad alcuni metodi (uguali o diversi) possono causare stati incoerenti. Tuttavia, i metodi BeginSend()
e BeginReceive()
sono thread-safe rispetto a se stessi.
È sicuro avere più chiamate in sospeso a ciascuna (o entrambe).
Nel caso di BeginReceive()
, verranno serviti quando i dati sono disponibili nell'ordine richiamato. Questo può essere utile se, ad esempio, l'elaborazione è lunga ma si desidera che altri ricevano il più rapidamente possibile. Ovviamente in questo caso è possibile che il proprio codice elabori più scontrini contemporaneamente e potrebbe essere necessaria la propria logica di sincronizzazione per proteggere lo stato dell'applicazione.
Nel caso di BeginSend()
, ciascuna chiamata tenterà di inviare i dati inviati nel buffer del socket e non appena viene accettata, verrà richiamata la chiamata (dove si chiamerà EndSend()
). Se lo spazio del buffer è insufficiente per ogni chiamata, verrà bloccato.
Nota: non impegna che il buffer di default 8k significa "Posso chiamare rapidamente BeginSend()
esattamente 8k dei dati, allora sarà bloccare", come la seguente condizione:
Il 8K è un numero "dimensione nominale", e il buffer possono restringersi e crescere alquanto
Come si queing la 8K pena di chiamate, dati vengono inviati sulla rete ridurre tale 8K dei dati accodati
In generale:
Se si chiama
BeginSend()
più volte all'interno di un thread, si ha la certezza che le mandate lascerà la macchina nell'ordine in cui sono stati chiamati.Se si chiama
BeginSend()
da più thread, non è possibile garantire l'ordine a meno che non si utilizzi un altro meccanismo di blocco per forzare le chiamate effettive a verificarsi in un ordine specifico. Ogni chiamata tuttavia invierà i suoi dati correttamente in un flusso contiguo di byte di rete.
La tua risposta è arrivata un paio d'anni dopo la domanda originale e ora lo sto vedendo (un altro anno dopo) ma voglio che tu sappia che ha avuto grandi dettagli e lo apprezzo molto. Anche se, la mia conoscenza personale del framework .Net e le mie capacità di sviluppatore sono ormai lontane da questa domanda, questa risposta sarà una grande risorsa per i futuri lettori. Se non avessi già controllato una risposta come risposta corretta anni fa, ti darei la risposta corretta. Molto apprezzato. – Dabloons
Mentre funzionerà, dovresti farlo solo con un protocollo basato su datagramma inaffidabile come UDP. Il motivo è che se due thread cercano di chiamare BeginSend, è possibile che l'ordine non venga inviato all'origine. Ciò comporterebbe il danneggiamento dei dati dell'applicazione quando si utilizza TCP. –