2012-04-13 1 views
10

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?

+1

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. –

risposta

7

Ho trovato un sorriso post on the MSDN forum che sembra rispondere alla tua domanda.

  1. È 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. [...]

+1

Non lo sapevo, grazie! – covertCoder

+1

Questo è esattamente quello che stavo cercando! GRAZIE! – Dabloons

11

.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:

  1. Il 8K è un numero "dimensione nominale", e il buffer possono restringersi e crescere alquanto

  2. 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.

+0

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