2014-08-04 13 views
5

So qualcosa sull'IOCP, ma sono un po 'confuso con APM.in C#, ci sono due thread quando chiamo BeginXXX

static FileStream fs; 
static void Main(string[] args) 
{ 
    fs = new FileStream(@"c:\bigfile.txt", FileMode.Open); 
    var buffer = new byte[10000000]; 
    IAsyncResult asyncResult = fs.BeginRead(buffer, 0, 10000000, OnCompletedRead, null); 
    Console.WriteLine("async..."); 
    int bytesRead = fs.EndRead(asyncResult); 
    Console.WriteLine("async... over"); 
} 

static void OnCompletedRead(IAsyncResult ar) 
{ 
     Console.WriteLine("finished"); 
} 

mi chiedo, è l'azione di lettura eseguita da un filo IO asincrono? O un thread di lavoro in un pool di thread?

E la funzione di richiamata OnCompletedRead è anch'essa eseguita da un thread IO nel pool di thread CLR?

Questi due fili sono uguali? In caso contrario, vengono generati due thread, uno esegue l'azione di lettura e un altro esegue la richiamata.

+0

Non chiamare "EndReceive" in "Principale". Dovresti invece chiamarlo in "OnCompleteRead" altrimenti non ottieni nessuno dei vantaggi delle chiamate asincrone. –

+3

Mi raccomando anche di leggere http://blog.stephencleary.com/2013/11/there-is-no-thread.html –

+0

Ho letto quel blog. Quindi non c'è thread per elaborare l'azione di lettura. Ma la callback viene eseguita sul thread di I/O, giusto? –

risposta

5

Se non si utilizza un argomento AsyncCallback con BeginRead, nel programma viene eseguito solo un thread. Questo utilizza le porte di completamento dell'IO per segnalare quando l'I/O è completo eseguendo una piccola quantità di codice su un thread nel pool di thread I/O per aggiornare lo stato dell'operazione come completo. Quando chiami EndRead bloccherà il thread corrente fino al completamento dell'operazione IO. È asincrono in quanto quando si avvia l'operazione di lettura il thread corrente non ha bisogno di fare altro che attendere che l'hardware IO esegua l'operazione di lettura, così puoi fare altre cose nel frattempo e poi decidere quando vuoi fermarti e aspetta che l'IO finisca.

Se passa un AsyncCallback poi, quando l'operazione è stata completata IO eseguirà una piccola quantità di codice su un IO filo pool di thread che attiverà il tuo metodo di callback per essere eseguito su un thread dal pool di thread .NET .

+0

Quindi l'OnCompletedRead viene eseguito sul thread I/O ?? –

+0

vuoi dire che la funzione di callback è preceduta dal thread principale? veramente? Io non la penso così –

+0

@roast_soul dipende dall'implementazione di 'BeginXxxxx' alcuni metodi cattureranno il contesto di sincronizzazione ed eseguiranno la chiamata sul thread nel contesto, altri useranno un thread threadpool per l'esecuzione quando la porta di completamento dell'IO segnala che i dati sono pronti . Non è definito in [APM] (http://msdn.microsoft.com/en-us/library/ms228963 (v = vs.110) .aspx) a differenza di async/await che controlla sempre 'SynchronizationContext' a meno che non dirlo a '.ConfigureAwait (false)'. –

2

Di solito, mclaassen ha ragione circa la natura del lavoro legato all'IO, IOCP e l'APM. Quando viene eseguito BeginRead, lo fa in modo asincrono fino alla modalità kernel. Ma c'è un avvertimento specifico nel tuo esempio che non ha menzionato nella sua risposta.

Nell'esempio si utilizza la classe FileStream. Un importante cosa da notare è che se non si utilizza il FileStream overload che accetta un valore booleano useAsync, quando si richiama un'operazione BeginWrite/EndWrite, lo farà lavoro di coda su un nuovo ThreadPool filo.

Questo è il sovraccarico di corretta:

public FileStream(
    string path, 
    FileMode mode, 
    FileAccess access, 
    FileShare share, 
    int bufferSize, 
    bool useAsync 
) 

Da MSDN:

useAsync:

Tipo: System.Boolean

Specifica se utilizzare asincrono I/O o I/O sincrono. Tuttavia, si noti che il sistema operativo sottostante potrebbe non supportare l'I/O asincrono, pertanto, quando si specifica true, l'handle potrebbe essere aperto in modo sincrono a seconda della piattaforma. Se aperti in modo asincrono, i metodi BeginRead e BeginWrite funzionano meglio su letture o scritture di grandi dimensioni, ma potrebbero essere molto più lenti per letture o scritture di piccole dimensioni. Se l'applicazione è progettata per sfruttare il vantaggio di di I/O asincrono, impostare il parametro useAsync su true. Utilizzo I/O asincrono correttamente può accelerare le applicazioni di ben come fattore di 10, ma il suo utilizzo senza riprogettare l'applicazione di I/O asincrono può ridurre le prestazioni anche del fattore di 10.

È necessario assicurarsi che ogni specifico metodo che implementa il pattern APM utilizzi veramente il vero lavoro asincrono fino in fondo.

Problemi correlati