Nota
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare ad accedere o modificare le directory.
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare a modificare le directory.
Usando Task.WhenAny, è possibile avviare più attività contemporaneamente ed elaborarle una alla volta man mano che vengono completate anziché elaborarle nell'ordine in cui vengono avviate.
Nell'esempio seguente viene utilizzata una query per creare una raccolta di attività. Ogni attività scarica il contenuto di un sito Web specificato. In ogni iterazione di un ciclo while, una chiamata attesa a WhenAny
restituisce il task nella raccolta di task che completa per primo il download. Tale attività viene rimossa dalla raccolta ed elaborata. Il ciclo si ripete fino a quando la raccolta non contiene altre attività.
Annotazioni
Per eseguire gli esempi, è necessario che Nel computer sia installato Visual Studio 2012 o versione successiva e .NET Framework 4.5 o versione successiva.
Download dell'esempio
È possibile scaricare il progetto Windows Presentation Foundation (WPF) completo da Esempio asincrono: Ottimizzazione dell'applicazione e quindi seguire questa procedura.
Decomprimere il file scaricato e quindi avviare Visual Studio.
Sulla barra dei menu scegliere File, Apri, Progetto/Soluzione.
Nella finestra di dialogo Apri progetto aprire la cartella contenente il codice di esempio decompresso e quindi aprire il file della soluzione (.sln) per AsyncFineTuningVB.
In Esplora soluzioni aprire il menu di scelta rapida per il progetto ProcessTasksAsTheyFinish e quindi scegliere Imposta come progetto di avvio.
Scegliere il tasto F5 per eseguire il progetto.
Scegliere i tasti CTRL+F5 per eseguire il progetto senza eseguirne il debug.
Eseguire il progetto più volte per verificare che le lunghezze scaricate non vengano sempre visualizzate nello stesso ordine.
Se non si vuole scaricare il progetto, è possibile esaminare il file di MainWindow.xaml.vb alla fine di questo argomento.
Compilazione dell'esempio
Questo esempio amplia il codice sviluppato in Annulla attività asincrone rimanenti dopo un'operazione completata (Visual Basic) e utilizza la stessa interfaccia utente.
Per compilare manualmente l'esempio passo dopo passo, seguire le istruzioni nella sezione "Download dell'Esempio", ma scegliere CancelAfterOneTask come progetto di avvio. Aggiungi le modifiche di questo argomento al metodo AccessTheWebAsync
in quel progetto. Le modifiche sono contrassegnate con asterischi.
Il progetto CancelAfterOneTask include già una query che, quando eseguita, crea una raccolta di attività. Ogni chiamata a ProcessURLAsync
nel codice seguente restituisce un oggetto Task<TResult> dove TResult
è un numero intero.
Dim downloadTasksQuery As IEnumerable(Of Task(Of Integer)) =
From url In urlList Select ProcessURLAsync(url, client, ct)
Nel file MainWindow.xaml.vb del progetto apportare le modifiche seguenti al AccessTheWebAsync
metodo .
Eseguire la query applicando Enumerable.ToList invece di ToArray.
Dim downloadTasks As List(Of Task(Of Integer)) = downloadTasksQuery.ToList()
Aggiungere un ciclo while che esegue i seguenti passaggi per ogni attività nella raccolta.
Attende una chiamata a
WhenAny
per identificare la prima attività nella raccolta che completa il suo scaricamento.Dim finishedTask As Task(Of Integer) = Await Task.WhenAny(downloadTasks)
Rimuove l'attività dalla raccolta.
downloadTasks.Remove(finishedTask)
Attende
finishedTask
, che è restituito da una chiamata aProcessURLAsync
. LafinishedTask
variabile è un Task<TResult> oggetto doveTReturn
è un numero intero. L'attività è già stata completata, ma si attende che venga recuperata la lunghezza del sito Web scaricato, come illustrato nell'esempio seguente.Dim length = Await finishedTask resultsTextBox.Text &= String.Format(vbCrLf & "Length of the downloaded website: {0}" & vbCrLf, length)
È consigliabile eseguire il progetto più volte per verificare che le lunghezze scaricate non vengano sempre visualizzate nello stesso ordine.
Attenzione
È possibile usare WhenAny
in un ciclo, come descritto nell'esempio, per risolvere i problemi che coinvolgono un numero ridotto di attività. Tuttavia, altri approcci sono più efficienti se si dispone di un numero elevato di attività da elaborare. Per altre informazioni ed esempi, vedere Elaborazione delle attività man mano che vengono completate.
Esempio completo
Il codice seguente è il testo completo del file MainWindow.xaml.vb per l'esempio. Gli asterischi contrassegnano gli elementi aggiunti per questo esempio.
Si noti che è necessario aggiungere un riferimento per System.Net.Http.
È possibile scaricare il progetto da Esempio asincrono: Ottimizzazione dell'applicazione.
' Add an Imports directive and a reference for System.Net.Http.
Imports System.Net.Http
' Add the following Imports directive for System.Threading.
Imports System.Threading
Class MainWindow
' Declare a System.Threading.CancellationTokenSource.
Dim cts As CancellationTokenSource
Private Async Sub startButton_Click(sender As Object, e As RoutedEventArgs)
' Instantiate the CancellationTokenSource.
cts = New CancellationTokenSource()
resultsTextBox.Clear()
Try
Await AccessTheWebAsync(cts.Token)
resultsTextBox.Text &= vbCrLf & "Downloads complete."
Catch ex As OperationCanceledException
resultsTextBox.Text &= vbCrLf & "Downloads canceled." & vbCrLf
Catch ex As Exception
resultsTextBox.Text &= vbCrLf & "Downloads failed." & vbCrLf
End Try
' Set the CancellationTokenSource to Nothing when the download is complete.
cts = Nothing
End Sub
' You can still include a Cancel button if you want to.
Private Sub cancelButton_Click(sender As Object, e As RoutedEventArgs)
If cts IsNot Nothing Then
cts.Cancel()
End If
End Sub
' Provide a parameter for the CancellationToken.
' Change the return type to Task because the method has no return statement.
Async Function AccessTheWebAsync(ct As CancellationToken) As Task
Dim client As HttpClient = New HttpClient()
' Call SetUpURLList to make a list of web addresses.
Dim urlList As List(Of String) = SetUpURLList()
' ***Create a query that, when executed, returns a collection of tasks.
Dim downloadTasksQuery As IEnumerable(Of Task(Of Integer)) =
From url In urlList Select ProcessURLAsync(url, client, ct)
' ***Use ToList to execute the query and start the download tasks.
Dim downloadTasks As List(Of Task(Of Integer)) = downloadTasksQuery.ToList()
' ***Add a loop to process the tasks one at a time until none remain.
While downloadTasks.Count > 0
' ***Identify the first task that completes.
Dim finishedTask As Task(Of Integer) = Await Task.WhenAny(downloadTasks)
' ***Remove the selected task from the list so that you don't
' process it more than once.
downloadTasks.Remove(finishedTask)
' ***Await the first completed task and display the results.
Dim length = Await finishedTask
resultsTextBox.Text &= String.Format(vbCrLf & "Length of the downloaded website: {0}" & vbCrLf, length)
End While
End Function
' Bundle the processing steps for a website into one async method.
Async Function ProcessURLAsync(url As String, client As HttpClient, ct As CancellationToken) As Task(Of Integer)
' GetAsync returns a Task(Of HttpResponseMessage).
Dim response As HttpResponseMessage = Await client.GetAsync(url, ct)
' Retrieve the website contents from the HttpResponseMessage.
Dim urlContents As Byte() = Await response.Content.ReadAsByteArrayAsync()
Return urlContents.Length
End Function
' Add a method that creates a list of web addresses.
Private Function SetUpURLList() As List(Of String)
Dim urls = New List(Of String) From
{
"https://msdn.microsoft.com",
"https://msdn.microsoft.com/library/hh290138.aspx",
"https://msdn.microsoft.com/library/hh290140.aspx",
"https://msdn.microsoft.com/library/dd470362.aspx",
"https://msdn.microsoft.com/library/aa578028.aspx",
"https://msdn.microsoft.com/library/ms404677.aspx",
"https://msdn.microsoft.com/library/ff730837.aspx"
}
Return urls
End Function
End Class
' Sample output:
' Length of the download: 226093
' Length of the download: 412588
' Length of the download: 175490
' Length of the download: 204890
' Length of the download: 158855
' Length of the download: 145790
' Length of the download: 44908
' Downloads complete.