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.
Quando si include codice asincrono nell'app, è consigliabile prendere in considerazione ed eventualmente impedire la reentrancy, che si riferisce alla reinserimento di un'operazione asincrona prima del completamento. Se non si identificano e gestiscono le possibilità di rientro, ciò può causare risultati imprevisti.
Annotazioni
Per eseguire l'esempio, è necessario che Nel computer sia installato Visual Studio 2012 o versione successiva e .NET Framework 4.5 o versione successiva.
Annotazioni
Transport Layer Security (TLS) versione 1.2 è ora la versione minima da usare nello sviluppo di app. Se l'app è destinata a una versione di .NET Framework precedente alla 4.7, vedere l'articolo seguente per le procedure consigliate di Transport Layer Security (TLS) con .NET Framework.
Riconoscimento della ri-entrabilità
Nell'esempio di questo argomento, gli utenti scelgono un pulsante Start per avviare un'app asincrona che scarica una serie di siti Web e calcola il numero totale di byte scaricati. Una versione sincrona dell'esempio risponde allo stesso modo indipendentemente dal numero di volte in cui un utente sceglie il pulsante perché, dopo la prima volta, il thread dell'interfaccia utente ignora tali eventi fino al termine dell'esecuzione dell'app. In un'app asincrona, tuttavia, il thread dell'interfaccia utente continua a rispondere e potrebbe essere necessario immettere nuovamente l'operazione asincrona prima del completamento.
L'esempio seguente mostra l'output previsto se l'utente sceglie il pulsante Start una sola volta. Viene visualizzato un elenco dei siti Web scaricati con le dimensioni, in byte, di ogni sito. Alla fine viene visualizzato il numero totale di byte.
1. msdn.microsoft.com/library/hh191443.aspx 83732
2. msdn.microsoft.com/library/aa578028.aspx 205273
3. msdn.microsoft.com/library/jj155761.aspx 29019
4. msdn.microsoft.com/library/hh290140.aspx 117152
5. msdn.microsoft.com/library/hh524395.aspx 68959
6. msdn.microsoft.com/library/ms404677.aspx 197325
7. msdn.microsoft.com 42972
8. msdn.microsoft.com/library/ff730837.aspx 146159
TOTAL bytes returned: 890591
Tuttavia, se l'utente sceglie più volte il pulsante, il gestore eventi viene richiamato ripetutamente e il processo di download viene immesso di nuovo ogni volta. Di conseguenza, diverse operazioni asincrone vengono eseguite contemporaneamente. L'output interlaccia i risultati e il numero totale di byte risulta confuso.
1. msdn.microsoft.com/library/hh191443.aspx 83732
2. msdn.microsoft.com/library/aa578028.aspx 205273
3. msdn.microsoft.com/library/jj155761.aspx 29019
4. msdn.microsoft.com/library/hh290140.aspx 117152
5. msdn.microsoft.com/library/hh524395.aspx 68959
1. msdn.microsoft.com/library/hh191443.aspx 83732
2. msdn.microsoft.com/library/aa578028.aspx 205273
6. msdn.microsoft.com/library/ms404677.aspx 197325
3. msdn.microsoft.com/library/jj155761.aspx 29019
7. msdn.microsoft.com 42972
4. msdn.microsoft.com/library/hh290140.aspx 117152
8. msdn.microsoft.com/library/ff730837.aspx 146159
TOTAL bytes returned: 890591
5. msdn.microsoft.com/library/hh524395.aspx 68959
1. msdn.microsoft.com/library/hh191443.aspx 83732
2. msdn.microsoft.com/library/aa578028.aspx 205273
6. msdn.microsoft.com/library/ms404677.aspx 197325
3. msdn.microsoft.com/library/jj155761.aspx 29019
4. msdn.microsoft.com/library/hh290140.aspx 117152
7. msdn.microsoft.com 42972
5. msdn.microsoft.com/library/hh524395.aspx 68959
8. msdn.microsoft.com/library/ff730837.aspx 146159
TOTAL bytes returned: 890591
6. msdn.microsoft.com/library/ms404677.aspx 197325
7. msdn.microsoft.com 42972
8. msdn.microsoft.com/library/ff730837.aspx 146159
TOTAL bytes returned: 890591
È possibile esaminare il codice che produce questo output scorrendo fino alla fine di questo argomento. È possibile sperimentare il codice scaricando la soluzione nel computer locale e quindi eseguendo il progetto WebsiteDownload o usando il codice alla fine di questo argomento per creare il proprio progetto Per altre informazioni e istruzioni, vedere Revisione ed esecuzione dell'app di esempio.
Gestione della ricalcatezza
Puoi gestire la reentrancy in diversi modi, a seconda di ciò che vuoi che l'app faccia. In questo argomento vengono illustrati gli esempi seguenti:
Disabilitare il pulsante Start
Disabilitare il pulsante Start mentre l'operazione è in esecuzione in modo che l'utente non possa interromperlo.
Annullare e riavviare l'operazione
Annullare qualsiasi operazione ancora in esecuzione quando l'utente sceglie di nuovo il pulsante Avvia e quindi lasciare che l'operazione richiesta più di recente continui.
Eseguire più operazioni e accodare i risultati
Consentire l'esecuzione asincrona di tutte le operazioni richieste, ma coordinare la visualizzazione dell'output in modo che i risultati di ogni operazione vengano visualizzati insieme e in ordine.
Disabilitare il pulsante Start
È possibile bloccare il pulsante Start mentre un'operazione è in esecuzione disabilitando il pulsante nella parte superiore del StartButton_Click gestore eventi. È quindi possibile riabilitare il pulsante dall'interno di un Finally blocco al termine dell'operazione in modo che gli utenti possano eseguire di nuovo l'app.
Il codice seguente mostra queste modifiche, contrassegnate con asterischi. È possibile aggiungere le modifiche al codice alla fine di questo argomento oppure scaricare l'app completata da Async Samples: Reentrancy nelle app desktop .NET. Il nome del progetto è DisableStartButton.
Private Async Sub StartButton_Click(sender As Object, e As RoutedEventArgs)
' This line is commented out to make the results clearer in the output.
'ResultsTextBox.Text = ""
' ***Disable the Start button until the downloads are complete.
StartButton.IsEnabled = False
Try
Await AccessTheWebAsync()
Catch ex As Exception
ResultsTextBox.Text &= vbCrLf & "Downloads failed."
' ***Enable the Start button in case you want to run the program again.
Finally
StartButton.IsEnabled = True
End Try
End Sub
In seguito alle modifiche, il pulsante non risponde durante AccessTheWebAsync il download dei siti Web, quindi il processo non può essere nuovamente immesso.
Annullare e riavviare l'operazione
Invece di disabilitare il pulsante Start , è possibile mantenere attivo il pulsante, ma, se l'utente sceglie di nuovo il pulsante, annullare l'operazione già in esecuzione e lasciare che l'operazione avviata più di recente continui.
Per ulteriori informazioni sull'annullamento, vedere Fine-Tuning La tua applicazione asincrona (Visual Basic).
Per configurare questo scenario, apportare le modifiche seguenti al codice di base fornito in Revisione ed esecuzione dell'app di esempio. È anche possibile scaricare l'app completa da Async Samples: Reentrancy nelle app .NET desktop. Il nome di questo progetto è CancelAndRestart.
Dichiarare una CancellationTokenSource variabile,
cts, che sia accessibile a tutti i metodi.Class MainWindow // Or Class MainPage ' *** Declare a System.Threading.CancellationTokenSource. Dim cts As CancellationTokenSourceIn
StartButton_Clickdeterminare se è già in corso un'operazione. Se il valore dictsèNothing, non è già attiva alcuna operazione. Se il valore non èNothing, l'operazione già in esecuzione viene annullata.' *** If a download process is already underway, cancel it. If cts IsNot Nothing Then cts.Cancel() End IfImpostare su
ctsun valore diverso che rappresenta il processo corrente.' *** Now set cts to cancel the current process if the button is chosen again. Dim newCTS As CancellationTokenSource = New CancellationTokenSource() cts = newCTSAlla fine di
StartButton_Click, il processo corrente è stato completato, quindi impostare di nuovo il valore dictssuNothing.' *** When the process completes, signal that another process can proceed. If cts Is newCTS Then cts = Nothing End If
Il codice seguente mostra tutte le modifiche in StartButton_Click. Le aggiunte sono contrassegnate con asterischi.
Private Async Sub StartButton_Click(sender As Object, e As RoutedEventArgs)
' This line is commented out to make the results clearer.
'ResultsTextBox.Text = ""
' *** If a download process is underway, cancel it.
If cts IsNot Nothing Then
cts.Cancel()
End If
' *** Now set cts to cancel the current process if the button is chosen again.
Dim newCTS As CancellationTokenSource = New CancellationTokenSource()
cts = newCTS
Try
' *** Send a token to carry the message if the operation is canceled.
Await AccessTheWebAsync(cts.Token)
Catch ex As OperationCanceledException
ResultsTextBox.Text &= vbCrLf & "Download canceled." & vbCrLf
Catch ex As Exception
ResultsTextBox.Text &= vbCrLf & "Downloads failed."
End Try
' *** When the process is complete, signal that another process can proceed.
If cts Is newCTS Then
cts = Nothing
End If
End Sub
In AccessTheWebAsyncapportare le modifiche seguenti.
Aggiungere un parametro per accettare il token di annullamento da
StartButton_Click.Utilizzare il metodo GetAsync per scaricare i siti Web perché
GetAsyncaccetta un parametro CancellationToken.Prima di chiamare
DisplayResultsper visualizzare i risultati per ogni sito Web scaricato, verificarectche l'operazione corrente non sia stata annullata.
Il codice seguente mostra queste modifiche, contrassegnate con asterischi.
' *** Provide a parameter for the CancellationToken from StartButton_Click.
Private Async Function AccessTheWebAsync(ct As CancellationToken) As Task
' Declare an HttpClient object.
Dim client = New HttpClient()
' Make a list of web addresses.
Dim urlList As List(Of String) = SetUpURLList()
Dim total = 0
Dim position = 0
For Each url In urlList
' *** Use the HttpClient.GetAsync method because it accepts a
' cancellation token.
Dim response As HttpResponseMessage = Await client.GetAsync(url, ct)
' *** Retrieve the website contents from the HttpResponseMessage.
Dim urlContents As Byte() = Await response.Content.ReadAsByteArrayAsync()
' *** Check for cancellations before displaying information about the
' latest site.
ct.ThrowIfCancellationRequested()
position += 1
DisplayResults(url, urlContents, position)
' Update the total.
total += urlContents.Length
Next
' Display the total count for all of the websites.
ResultsTextBox.Text &=
String.Format(vbCrLf & vbCrLf & "TOTAL bytes returned: " & total & vbCrLf)
End Function
Se si sceglie il pulsante Start più volte mentre l'app è in esecuzione, dovrebbe produrre risultati simili all'output seguente:
1. msdn.microsoft.com/library/hh191443.aspx 83732
2. msdn.microsoft.com/library/aa578028.aspx 205273
3. msdn.microsoft.com/library/jj155761.aspx 29019
4. msdn.microsoft.com/library/hh290140.aspx 122505
5. msdn.microsoft.com/library/hh524395.aspx 68959
6. msdn.microsoft.com/library/ms404677.aspx 197325
Download canceled.
1. msdn.microsoft.com/library/hh191443.aspx 83732
2. msdn.microsoft.com/library/aa578028.aspx 205273
3. msdn.microsoft.com/library/jj155761.aspx 29019
Download canceled.
1. msdn.microsoft.com/library/hh191443.aspx 83732
2. msdn.microsoft.com/library/aa578028.aspx 205273
3. msdn.microsoft.com/library/jj155761.aspx 29019
4. msdn.microsoft.com/library/hh290140.aspx 117152
5. msdn.microsoft.com/library/hh524395.aspx 68959
6. msdn.microsoft.com/library/ms404677.aspx 197325
7. msdn.microsoft.com 42972
8. msdn.microsoft.com/library/ff730837.aspx 146159
TOTAL bytes returned: 890591
Per eliminare gli elenchi parziali, rimuovere il commento dalla prima riga di codice in StartButton_Click per cancellare la casella di testo ogni volta che l'utente riavvia l'operazione.
Eseguire più operazioni e mettere in coda l'output
Questo terzo esempio è il più complicato in quanto l'app avvia un'altra operazione asincrona ogni volta che l'utente sceglie il pulsante Start e tutte le operazioni vengono eseguite fino al completamento. Tutte le operazioni richieste scaricano siti Web dall'elenco in modo asincrono, ma l'output delle operazioni viene presentato in sequenza. Cioè, l'attività di download effettiva viene intercalata, come illustrato dall'output in Recognizing Reentrancy, ma l'elenco dei risultati per ogni gruppo viene presentato separatamente.
Le operazioni condividono un oggetto globale Task, pendingWork, che funge da gatekeeper per il processo di visualizzazione.
È possibile eseguire questo esempio incollando le modifiche nel codice in Compilazione dell'app oppure seguendo le istruzioni in Download dell'app per scaricare l'esempio e quindi eseguire il progetto QueueResults.
L'output seguente mostra il risultato se l'utente sceglie il pulsante Start una sola volta. L'etichetta lettera, A, indica che il risultato proviene dalla prima scelta del pulsante Start . I numeri mostrano l'ordine degli URL nell'elenco delle destinazioni di download.
#Starting group A.
#Task assigned for group A.
A-1. msdn.microsoft.com/library/hh191443.aspx 87389
A-2. msdn.microsoft.com/library/aa578028.aspx 209858
A-3. msdn.microsoft.com/library/jj155761.aspx 30870
A-4. msdn.microsoft.com/library/hh290140.aspx 119027
A-5. msdn.microsoft.com/library/hh524395.aspx 71260
A-6. msdn.microsoft.com/library/ms404677.aspx 199186
A-7. msdn.microsoft.com 53266
A-8. msdn.microsoft.com/library/ff730837.aspx 148020
TOTAL bytes returned: 918876
#Group A is complete.
Se l'utente sceglie il pulsante Start tre volte, l'app genera un output simile alle righe seguenti. Le righe di informazioni che iniziano con un segno di cancelletto (#) tracciano lo stato di avanzamento dell'applicazione.
#Starting group A.
#Task assigned for group A.
A-1. msdn.microsoft.com/library/hh191443.aspx 87389
A-2. msdn.microsoft.com/library/aa578028.aspx 207089
A-3. msdn.microsoft.com/library/jj155761.aspx 30870
A-4. msdn.microsoft.com/library/hh290140.aspx 119027
A-5. msdn.microsoft.com/library/hh524395.aspx 71259
A-6. msdn.microsoft.com/library/ms404677.aspx 199185
#Starting group B.
#Task assigned for group B.
A-7. msdn.microsoft.com 53266
#Starting group C.
#Task assigned for group C.
A-8. msdn.microsoft.com/library/ff730837.aspx 148010
TOTAL bytes returned: 916095
B-1. msdn.microsoft.com/library/hh191443.aspx 87389
B-2. msdn.microsoft.com/library/aa578028.aspx 207089
B-3. msdn.microsoft.com/library/jj155761.aspx 30870
B-4. msdn.microsoft.com/library/hh290140.aspx 119027
B-5. msdn.microsoft.com/library/hh524395.aspx 71260
B-6. msdn.microsoft.com/library/ms404677.aspx 199186
#Group A is complete.
B-7. msdn.microsoft.com 53266
B-8. msdn.microsoft.com/library/ff730837.aspx 148010
TOTAL bytes returned: 916097
C-1. msdn.microsoft.com/library/hh191443.aspx 87389
C-2. msdn.microsoft.com/library/aa578028.aspx 207089
#Group B is complete.
C-3. msdn.microsoft.com/library/jj155761.aspx 30870
C-4. msdn.microsoft.com/library/hh290140.aspx 119027
C-5. msdn.microsoft.com/library/hh524395.aspx 72765
C-6. msdn.microsoft.com/library/ms404677.aspx 199186
C-7. msdn.microsoft.com 56190
C-8. msdn.microsoft.com/library/ff730837.aspx 148010
TOTAL bytes returned: 920526
#Group C is complete.
I gruppi B e C iniziano prima del completamento del gruppo A, ma l'output per ogni gruppo viene visualizzato separatamente. Tutto l'output per il gruppo A viene visualizzato per primo, seguito da tutto l'output per il gruppo B e quindi da tutto l'output per il gruppo C. L'app visualizza sempre i gruppi in ordine e, per ogni gruppo, visualizza sempre le informazioni sui singoli siti Web nell'ordine in cui gli URL vengono visualizzati nell'elenco degli URL.
Tuttavia, non è possibile prevedere l'ordine in cui si verificano effettivamente i download. Dopo l'avvio di più gruppi, le attività di download generate sono tutte attive. Non puoi presupporre che A-1 verrà scaricato prima di B-1 e non puoi presupporre che A-1 verrà scaricato prima di A-2.
Definizioni globali
Il codice di esempio contiene le due dichiarazioni globali seguenti visibili da tutti i metodi.
Class MainWindow ' Class MainPage in Windows Store app.
' ***Declare the following variables where all methods can access them.
Private pendingWork As Task = Nothing
Private group As Char = ChrW(AscW("A") - 1)
La Task variabile, pendingWork, supervisiona il processo di visualizzazione e impedisce a qualsiasi gruppo di interrompere l'operazione di visualizzazione di un altro gruppo. La variabile di caratteri, group, etichetta l'output di gruppi diversi per verificare che i risultati vengano visualizzati nell'ordine previsto.
Il Gestore Eventi Click
Il gestore eventi, StartButton_Click, incrementa la lettera di gruppo ogni volta che l'utente sceglie il pulsante Start . Il gestore chiama AccessTheWebAsync quindi per eseguire l'operazione di download.
Private Async Sub StartButton_Click(sender As Object, e As RoutedEventArgs)
' ***Verify that each group's results are displayed together, and that
' the groups display in order, by marking each group with a letter.
group = ChrW(AscW(group) + 1)
ResultsTextBox.Text &= String.Format(vbCrLf & vbCrLf & "#Starting group {0}.", group)
Try
' *** Pass the group value to AccessTheWebAsync.
Dim finishedGroup As Char = Await AccessTheWebAsync(group)
' The following line verifies a successful return from the download and
' display procedures.
ResultsTextBox.Text &= String.Format(vbCrLf & vbCrLf & "#Group {0} is complete." & vbCrLf, finishedGroup)
Catch ex As Exception
ResultsTextBox.Text &= vbCrLf & "Downloads failed."
End Try
End Sub
Metodo AccessTheWebAsync
In questo esempio vengono suddivisi AccessTheWebAsync in due metodi. Il primo metodo, AccessTheWebAsync, avvia tutte le attività di download per un gruppo e configura pendingWork per controllare il processo di visualizzazione. Il metodo usa una query LINQ (Language Integrated Query) e ToArray per avviare tutte le attività di download contemporaneamente.
AccessTheWebAsync chiama quindi FinishOneGroupAsync per attendere il completamento di ogni download e visualizzarne la lunghezza.
FinishOneGroupAsync restituisce un'attività assegnata a pendingWork in AccessTheWebAsync. Tale valore impedisce l'interruzione di un'altra operazione prima del completamento dell'attività.
Private Async Function AccessTheWebAsync(grp As Char) As Task(Of Char)
Dim client = New HttpClient()
' Make a list of the web addresses to download.
Dim urlList As List(Of String) = SetUpURLList()
' ***Kick off the downloads. The application of ToArray activates all the download tasks.
Dim getContentTasks As Task(Of Byte())() =
urlList.Select(Function(addr) client.GetByteArrayAsync(addr)).ToArray()
' ***Call the method that awaits the downloads and displays the results.
' Assign the Task that FinishOneGroupAsync returns to the gatekeeper task, pendingWork.
pendingWork = FinishOneGroupAsync(urlList, getContentTasks, grp)
ResultsTextBox.Text &=
String.Format(vbCrLf & "#Task assigned for group {0}. Download tasks are active." & vbCrLf, grp)
' ***This task is complete when a group has finished downloading and displaying.
Await pendingWork
' You can do other work here or just return.
Return grp
End Function
Metodo FinishOneGroupAsync
Questo metodo scorre attraverso le attività di download di un gruppo, attendendo ciascuna, mostrando la lunghezza del sito Web scaricato e aggiungendo la lunghezza al totale.
La prima istruzione in FinishOneGroupAsync usa pendingWork per assicurarsi che l'immissione del metodo non interferisca con un'operazione già presente nella procedura di visualizzazione o che è già in attesa. Se tale operazione è in corso, l'operazione di immissione deve attendere il suo turno.
Private Async Function FinishOneGroupAsync(urls As List(Of String), contentTasks As Task(Of Byte())(), grp As Char) As Task
' Wait for the previous group to finish displaying results.
If pendingWork IsNot Nothing Then
Await pendingWork
End If
Dim total = 0
' contentTasks is the array of Tasks that was created in AccessTheWebAsync.
For i As Integer = 0 To contentTasks.Length - 1
' Await the download of a particular URL, and then display the URL and
' its length.
Dim content As Byte() = Await contentTasks(i)
DisplayResults(urls(i), content, i, grp)
total += content.Length
Next
' Display the total count for all of the websites.
ResultsTextBox.Text &=
String.Format(vbCrLf & vbCrLf & "TOTAL bytes returned: " & total & vbCrLf)
End Function
È possibile eseguire questo esempio incollando le modifiche nel codice in Compilazione dell'app oppure seguendo le istruzioni in Download dell'app per scaricare l'esempio e quindi eseguire il progetto QueueResults.
Punti di interesse
Le righe di informazioni che iniziano con un segno di cancelletto (#) nell'output chiariscono il funzionamento di questo esempio.
L'output mostra i modelli seguenti.
È possibile avviare un gruppo durante la visualizzazione dell'output di un gruppo precedente, ma la visualizzazione dell'output del gruppo precedente non viene interrotta.
#Starting group A. #Task assigned for group A. Download tasks are active. A-1. msdn.microsoft.com/library/hh191443.aspx 87389 A-2. msdn.microsoft.com/library/aa578028.aspx 207089 A-3. msdn.microsoft.com/library/jj155761.aspx 30870 A-4. msdn.microsoft.com/library/hh290140.aspx 119037 A-5. msdn.microsoft.com/library/hh524395.aspx 71260 #Starting group B. #Task assigned for group B. Download tasks are active. A-6. msdn.microsoft.com/library/ms404677.aspx 199186 A-7. msdn.microsoft.com 53078 A-8. msdn.microsoft.com/library/ff730837.aspx 148010 TOTAL bytes returned: 915919 B-1. msdn.microsoft.com/library/hh191443.aspx 87388 B-2. msdn.microsoft.com/library/aa578028.aspx 207089 B-3. msdn.microsoft.com/library/jj155761.aspx 30870 #Group A is complete. B-4. msdn.microsoft.com/library/hh290140.aspx 119027 B-5. msdn.microsoft.com/library/hh524395.aspx 71260 B-6. msdn.microsoft.com/library/ms404677.aspx 199186 B-7. msdn.microsoft.com 53078 B-8. msdn.microsoft.com/library/ff730837.aspx 148010 TOTAL bytes returned: 915908L'attività
pendingWorkèNothingall'inizio diFinishOneGroupAsyncsolo per il gruppo A, che ha iniziato per primo. Il gruppo A non ha ancora completato un'espressione await quando raggiungeFinishOneGroupAsync. Di conseguenza, il controllo non è tornato aAccessTheWebAsynce la prima assegnazione apendingWorknon è stata eseguita.Nell'output vengono sempre visualizzate le due righe seguenti. Il codice non viene mai interrotto tra l'avvio dell'operazione di un gruppo in
StartButton_Clicke l'assegnazione di un'attività per il gruppo apendingWork.#Starting group B. #Task assigned for group B. Download tasks are active.Dopo che un gruppo entra in
StartButton_Click, l'operazione non completa un'espressione await finché l'operazione non entra inFinishOneGroupAsync. Pertanto, nessun'altra operazione può ottenere il controllo durante il segmento di codice.
Revisione ed esecuzione dell'app di esempio
Per comprendere meglio l'app di esempio, è possibile scaricarla, compilarla manualmente o esaminare il codice alla fine di questo argomento senza implementare l'app.
Annotazioni
Per eseguire l'esempio come app desktop Windows Presentation Foundation (WPF), è necessario che nel computer sia installato Visual Studio 2012 o versione successiva e .NET Framework 4.5 o versione successiva.
Download dell'app
Scaricare il file compresso da Async Samples: Reentrancy in .NET Desktop Apps (Esempi asincroni: reentrancy in app desktop .NET).
Decomprimere il file scaricato e quindi avviare Visual Studio.
Sulla barra dei menu scegliere File, Apri, Progetto/Soluzione.
Passare alla cartella che contiene il codice di esempio decompresso e quindi aprire il file della soluzione (.sln).
In Esplora soluzioni aprire il menu di scelta rapida per il progetto da eseguire e quindi scegliere Imposta come StartUpProject.
Scegliere i tasti CTRL+F5 per compilare ed eseguire il progetto.
Compilazione dell'app
La sezione seguente fornisce il codice per compilare l'esempio come app WPF.
Per compilare un'app WPF
Avvia Visual Studio.
Nella barra dei menu scegliere File, Nuovo, Progetto.
Verrà visualizzata la finestra di dialogo Nuovo progetto .
Nel riquadro Modelli installati espandere Visual Basic, quindi espandere Windows.
Nell'elenco dei tipi di progetto scegliere Applicazione WPF.
Assegnare al progetto
WebsiteDownloadWPFil nome , scegliere .NET Framework versione 4.6 o successiva e quindi fare clic sul pulsante OK .Il nuovo progetto verrà visualizzato in Esplora soluzioni.
Nell'Editor di codice di Visual Studio scegliere la scheda MainWindow.xaml .
Se la scheda non è visibile, aprire il menu di scelta rapida per MainWindow.xaml in Esplora soluzioni e quindi scegliere Visualizza codice.
Nella visualizzazione XAML di MainWindow.xaml sostituire il codice con il codice seguente.
<Window x:Class="MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="using:WebsiteDownloadWPF" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d"> <Grid Width="517" Height="360"> <Button x:Name="StartButton" Content="Start" HorizontalAlignment="Left" Margin="-1,0,0,0" VerticalAlignment="Top" Click="StartButton_Click" Height="53" Background="#FFA89B9B" FontSize="36" Width="518" /> <TextBox x:Name="ResultsTextBox" HorizontalAlignment="Left" Margin="-1,53,0,-36" TextWrapping="Wrap" VerticalAlignment="Top" Height="343" FontSize="10" ScrollViewer.VerticalScrollBarVisibility="Visible" Width="518" FontFamily="Lucida Console" /> </Grid> </Window>Una finestra semplice che contiene una casella di testo e un pulsante viene visualizzato nella visualizzazione Progettazione di MainWindow.xaml.
In Esplora soluzioni fare clic con il pulsante destro del mouse su Riferimenti e scegliere Aggiungi riferimento.
Aggiungere un riferimento per System.Net.Http, se non è già selezionato.
In Esplora soluzioni aprire il menu di scelta rapida per MainWindow.xaml.vb e quindi scegliere Visualizza codice.
In MainWindow.xaml.vb sostituire il codice con il codice seguente.
' Add the following Imports statements, and add a reference for System.Net.Http. Imports System.Net.Http Imports System.Threading Class MainWindow Private Async Sub StartButton_Click(sender As Object, e As RoutedEventArgs) System.Net.ServicePointManager.SecurityProtocol = System.Net.ServicePointManager.SecurityProtocol Or System.Net.SecurityProtocolType.Tls12 ' This line is commented out to make the results clearer in the output. 'ResultsTextBox.Text = "" Try Await AccessTheWebAsync() Catch ex As Exception ResultsTextBox.Text &= vbCrLf & "Downloads failed." End Try End Sub Private Async Function AccessTheWebAsync() As Task ' Declare an HttpClient object. Dim client = New HttpClient() ' Make a list of web addresses. Dim urlList As List(Of String) = SetUpURLList() Dim total = 0 Dim position = 0 For Each url In urlList ' GetByteArrayAsync returns a task. At completion, the task ' produces a byte array. Dim urlContents As Byte() = Await client.GetByteArrayAsync(url) position += 1 DisplayResults(url, urlContents, position) ' Update the total. total += urlContents.Length Next ' Display the total count for all of the websites. ResultsTextBox.Text &= String.Format(vbCrLf & vbCrLf & "TOTAL bytes returned: " & total & vbCrLf) End Function Private Function SetUpURLList() As List(Of String) Dim urls = New List(Of String) From { "https://msdn.microsoft.com/library/hh191443.aspx", "https://msdn.microsoft.com/library/aa578028.aspx", "https://msdn.microsoft.com/library/jj155761.aspx", "https://msdn.microsoft.com/library/hh290140.aspx", "https://msdn.microsoft.com/library/hh524395.aspx", "https://msdn.microsoft.com/library/ms404677.aspx", "https://msdn.microsoft.com", "https://msdn.microsoft.com/library/ff730837.aspx" } Return urls End Function Private Sub DisplayResults(url As String, content As Byte(), pos As Integer) ' Display the length of each website. The string format is designed ' to be used with a monospaced font, such as Lucida Console or ' Global Monospace. ' Strip off the "http:'". Dim displayURL = url.Replace("https://", "") ' Display position in the URL list, the URL, and the number of bytes. ResultsTextBox.Text &= String.Format(vbCrLf & "{0}. {1,-58} {2,8}", pos, displayURL, content.Length) End Sub End ClassScegliere i tasti CTRL+F5 per eseguire il programma e quindi scegliere il pulsante Start più volte.
Apporta le modifiche da Disabilita il pulsante Start, a Annulla e riavvia l'operazione, oppure a Esegui più operazioni e accoda l'output per gestire la rientranza.