Cercando di capire alcuni comportamenti asincroni / attendi

4

Stavo lavorando su un po 'di codice per un progetto personale, quando ho scoperto la necessità di generare checksum su grandi quantità di file. Prima di tutto lasciatemi dire che ho già risolto questo problema idealmente usando System.Threading.Tasks.Parallel (.net net, C #), che si comporta come mi sarei aspettato. Quello che mi aspettavo era che diversi checksum funzionassero contemporaneamente usando Tasks, dato un elenco di compiti, ma non necessariamente sono stati elaborati in ordine. In altre parole, se ne inserisco uno piccolo (10mb forse) come ultimo e un file 5gb come primo, l'ultimo dovrebbe finire per primo. Perché richiede meno tempo per l'elaborazione.

Ecco un esempio molto semplice:

static async void MainAsync()
{
    await GetChecksum(1,@"E:\Files\ISOgbfile.iso");
    await GetChecksum(2,@"E:\Files\ISOgbfile.iso");
    await GetChecksum(3,@"E:\Files\ISOgbfile.iso");
    await GetChecksum(4,@"E:\Files\ISOmbfile.iso");
}

E la funzione GetCheckSum:

static async Task<string> GetChecksum(int index,string file)
{
    using (FileStream stream = File.OpenRead(file))
    {
        SHA256Managed sha = new SHA256Managed();
        Task<byte[]> checksum = sha.ComputeHashAsync(stream, 1200000);
        var ret = await checksum;
        System.Console.WriteLine($"{index} -> {file}");
        var hash = BitConverter.ToString(ret).Replace("-", String.Empty);
        System.Console.WriteLine($" ::{hash}");
        return hash;
    }
}

Secondo questo articolo:      link

Quali stati:

The method creates and starts three tasks of type Task, where TResult is an integer. As each task finishes, DisplayResults displays the task's URL and the length of the downloaded contents. Because the tasks are running asynchronously, the order in which the results appear might differ from the order in which they were declared.

Tuttavia non è quello che ho provato con questo esempio. Vedo ognuno finire nell'ordine in cui sono stati chiamati. In questo esempio mi rendo conto che non utilizza l'elaborazione parallela, presumo che imporrebbe l'utilizzo di un singolo processore, ma dato che l'ultimo richiede 2 secondi per l'elaborazione e il primo richiede 2 minuti, mi aspetterei ancora che il più piccolo dovrebbe finire prima.

Qualcuno può forse spiegare questo comportamento? Voglio solo capire cosa sta succedendo dietro le quinte con async e attendere quando usato in questo modo.

    
posta Brandon 05.04.2016 - 02:41
fonte

1 risposta

7

Quando lo chiami in questo modo:

await GetChecksum(1,@"E:\Files\ISOgbfile.iso");
await GetChecksum(2,@"E:\Files\ISOgbfile.iso");
await GetChecksum(3,@"E:\Files\ISOgbfile.iso");
await GetChecksum(4,@"E:\Files\ISOmbfile.iso");

Crea la prima attività, quindi attende che venga completata, quindi crea la seconda attività, quindi attende che sia completata, ecc.

Quando lo chiami in questo modo:

Task<string> task1 = GetChecksum(1,@"E:\Files\ISOgbfile.iso");
Task<string> task2 = GetChecksum(2,@"E:\Files\ISOgbfile.iso");
Task<string> task3 = GetChecksum(3,@"E:\Files\ISOgbfile.iso");
Task<string> task4 = GetChecksum(4,@"E:\Files\ISOmbfile.iso");

string checksum1 = await task1;
string checksum2 = await task2;
string checksum3 = await task3;
string checksum4 = await task4;

Crea tutti le attività e le avvia in esecuzione in parallelo, quindi attende il completamento del primo, quindi attende il completamento del secondo, ecc. La sintassi è importante. Arresta le istruzioni di esecuzione nel punto in cui chiamate await fino al termine dell'attività corrente.

    
risposta data 05.04.2016 - 03:22
fonte

Leggi altre domande sui tag