앱에 비동기 코드를 포함하는 경우 비동기 작업을 완료하기 전에 다시 입력하는 것을 의미하는 재진입을 고려하고 방지해야 합니다. 재진입 가능성을 식별하고 처리하지 않으면 예기치 않은 결과가 발생할 수 있습니다.
비고
예제를 실행하려면 Visual Studio 2012 이상과 .NET Framework 4.5 이상이 컴퓨터에 설치되어 있어야 합니다.
비고
TLS(전송 계층 보안) 버전 1.2는 이제 앱 개발에 사용할 최소 버전입니다. 앱이 4.7 이전의 .NET Framework 버전을 대상으로 하는 경우 .NET Framework를 사용하는 TLS(전송 계층 보안) 모범 사례에 대한 다음 문서를 참조하세요.
재진입 가능성 인식
이 항목의 예제에서 사용자는 시작 단추를 선택하여 일련의 웹 사이트를 다운로드하고 다운로드된 총 바이트 수를 계산하는 비동기 앱을 시작합니다. 이 예제의 동기 버전은 사용자가 단추를 선택한 횟수에 관계없이 동일한 방식으로 응답합니다. 첫 번째 이후 앱 실행이 완료될 때까지 UI 스레드가 해당 이벤트를 무시하기 때문입니다. 그러나 비동기 앱에서는 UI 스레드가 계속 응답하며, 완료되기 전에 비동기 작업을 다시 입력할 수 있습니다.
다음 예제에서는 사용자가 시작 단추를 한 번만 선택하는 경우 예상되는 출력을 보여 줍니다. 다운로드한 웹 사이트 목록은 각 사이트의 크기(바이트)로 표시됩니다. 끝에 표시되는 총 바이트 수입니다.
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
그러나 사용자가 단추를 두 번 이상 선택하면 이벤트 처리기가 반복적으로 호출되고 다운로드 프로세스가 매번 다시 입력됩니다. 따라서 여러 비동기 작업이 동시에 실행되고 출력이 결과를 인터리브하며 총 바이트 수가 혼동됩니다.
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
이 항목의 끝까지 스크롤하여 이 출력을 생성하는 코드를 검토할 수 있습니다. 로컬 컴퓨터에 솔루션을 다운로드한 다음 WebsiteDownload 프로젝트를 실행하거나 이 항목의 끝에 있는 코드를 사용하여 사용자 고유의 프로젝트를 만들어 코드를 실험할 수 있습니다. 자세한 내용 및 지침은 예제 앱 검토 및 실행을 참조하세요.
재진입 처리
앱의 수행 방식에 따라 다양한 방법으로 재진입을 처리할 수 있습니다. 이 항목에서는 다음 예제를 제공합니다.
-
사용자가 작업을 중단할 수 없도록 작업을 실행하는 동안 시작 단추를 사용하지 않도록 설정합니다.
-
사용자가 시작 단추를 다시 선택할 때 여전히 실행 중인 작업을 취소한 다음 가장 최근에 요청한 작업을 계속하도록 합니다.
-
요청된 모든 작업이 비동기적으로 실행되도록 허용하지만 각 작업의 결과가 순서대로 함께 표시되도록 출력 표시를 조정합니다.
시작 단추 사용 안 함
이벤트 처리기 맨 위에 있는 단추를 사용하지 않도록 설정하여 작업이 실행되는 동안 시작 단추를 차단할 StartButton_Click
수 있습니다. 그런 다음, 사용자가 앱을 다시 실행할 수 있도록 작업이 완료되면 블록 내에서 Finally
단추를 다시 활성화할 수 있습니다.
다음 코드에서는 별표로 표시된 이러한 변경 내용을 보여 줍니다. 이 항목의 끝에 코드에 변경 내용을 추가하거나 비동기 샘플: .NET Desktop Apps의 재진입에서 완성된 앱을 다운로드할 수 있습니다. 프로젝트 이름은 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
변경으로 인해 웹 사이트를 다운로드하는 동안 AccessTheWebAsync
단추가 응답하지 않으므로 프로세스를 다시 입력할 수 없습니다.
작업 취소 및 다시 시작
시작 단추를 사용하지 않도록 설정하는 대신 단추를 활성 상태로 유지할 수 있지만 사용자가 해당 단추를 다시 선택하는 경우 이미 실행 중인 작업을 취소하고 가장 최근에 시작된 작업을 계속할 수 있습니다.
취소에 대한 자세한 내용은 Fine-Tuning 비동기 애플리케이션(Visual Basic)을 참조하세요.
이 시나리오를 설정하려면 예제 앱 검토 및 실행에 제공되는 기본 코드를 다음과 같이 변경합니다. .NET 데스크톱 앱에서의 비동기 샘플: 재진입에서 완성된 앱을 다운로드할 수 있습니다. 이 프로젝트의 이름은 CancelAndRestart입니다.
모든 메서드에서 사용할 수 있는 CancellationTokenSource 범위의 변수
cts
를 선언합니다.Class MainWindow // Or Class MainPage ' *** Declare a System.Threading.CancellationTokenSource. Dim cts As CancellationTokenSource
에서
StartButton_Click
작업이 이미 진행 중인지 여부를 확인합니다. 값이cts
이면Nothing
작업이 활성화되어 있지 않습니다. 값이 없Nothing
으면 이미 실행 중인 작업이 취소됩니다.' *** If a download process is already underway, cancel it. If cts IsNot Nothing Then cts.Cancel() End If
현재 프로세스를 나타내는 다른 값으로 설정합니다
cts
.' *** Now set cts to cancel the current process if the button is chosen again. Dim newCTS As CancellationTokenSource = New CancellationTokenSource() cts = newCTS
끝부
StartButton_Click
분에 현재 프로세스가 완료되므로 다시cts
값을Nothing
.로 설정합니다.' *** When the process completes, signal that another process can proceed. If cts Is newCTS Then cts = Nothing End If
다음 코드는 StartButton_Click
내의 모든 변경 사항을 보여줍니다. 추가 항목은 별표로 표시됩니다.
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
AccessTheWebAsync
에서 다음을 변경하세요.
에서 취소 토큰
StartButton_Click
을 수락하는 매개 변수를 추가합니다.웹사이트를 다운로드하려면 GetAsync 메서드를 사용하십시오. 이는
GetAsync
가 CancellationToken 인수를 허용하기 때문입니다.다운로드한 각 웹 사이트에 대한 결과를 표시하기 위해 호출
DisplayResults
하기 전에 현재 작업이 취소되지 않았는지 확인ct
합니다.
다음 코드에서는 별표로 표시된 이러한 변경 내용을 보여 줍니다.
' *** 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
이 앱을 실행하는 동안 시작 단추를 여러 번 선택하면 다음 출력과 유사한 결과가 생성됩니다.
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
부분 목록을 제거하려면 사용자가 작업을 다시 시작할 때마다 첫 번째 코드 StartButton_Click
줄의 주석 처리를 제거하여 텍스트 상자를 지웁니다.
여러 작업 실행 및 출력 큐 대기
이 세 번째 예제는 사용자가 시작 단추를 선택할 때마다 앱이 다른 비동기 작업을 시작하고 모든 작업이 완료될 때까지 실행된다는 측면에서 가장 복잡합니다. 요청된 모든 작업은 목록에서 웹 사이트를 비동기적으로 다운로드하지만 작업의 출력은 순차적으로 표시됩니다. 즉, 재 진입 인식 의 출력에 표시된 것처럼 실제 다운로드 작업은 인터리브되지만 각 그룹에 대한 결과 목록은 별도로 표시됩니다.
운영은 디스플레이 프로세스의 게이트키퍼 역할을 하는 전역 TaskpendingWork
를 공유합니다.
앱 빌드의 코드에 변경 내용을 붙여넣어 이 예제를 실행하거나, 앱을 다운로드하는 지침에 따라 샘플을 다운로드한 다음 QueueResults 프로젝트를 실행할 수 있습니다.
다음 출력은 사용자가 시작 단추를 한 번만 선택하는 경우의 결과를 보여 줍니다. 문자 레이블 A는 시작 단추가 처음 선택된 시점의 결과임을 나타냅니다. 숫자는 다운로드 대상 목록에 있는 URL의 순서를 표시합니다.
#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.
사용자가 시작 단추를 세 번 선택하면 앱은 다음 줄과 유사한 출력을 생성합니다. 파운드 기호(#)로 시작하는 정보 줄은 애플리케이션의 진행률을 추적합니다.
#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.
그룹 A가 완료되기 전에 그룹 B와 C가 시작되지만 각 그룹에 대한 출력은 별도로 표시됩니다. 그룹 A에 대한 모든 출력이 먼저 나타나고, 그 다음에는 그룹 B의 모든 출력과 그룹 C에 대한 모든 출력이 표시됩니다. 앱은 항상 순서대로 그룹을 표시하고, 각 그룹에 대해 URL이 URL 목록에 표시되는 순서대로 개별 웹 사이트에 대한 정보를 항상 표시합니다.
그러나 다운로드가 실제로 발생하는 순서는 예측할 수 없습니다. 여러 그룹이 시작되면 생성되는 다운로드 작업이 모두 활성화됩니다. A-1이 B-1 이전에 다운로드된다고 가정할 수 없으며 A-1이 A-2 이전에 다운로드된다고 가정할 수 없습니다.
전 세계 정의
샘플 코드에는 모든 메서드에서 볼 수 있는 다음 두 개의 전역 선언이 포함되어 있습니다.
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)
변수Task
는 pendingWork
표시 프로세스를 감독하고 그룹이 다른 그룹의 표시 작업을 방해하지 않도록 합니다. 문자 변수는 group
다른 그룹의 출력에 레이블을 지정하여 결과가 예상 순서대로 표시되는지 확인합니다.
Click 이벤트 처리기
이벤트 처리기는 StartButton_Click
사용자가 시작 단추를 선택할 때마다 그룹 문자를 증가합니다. 그런 다음 처리기가 호출 AccessTheWebAsync
하여 다운로드 작업을 실행합니다.
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
AccessTheWebAsync 메서드
이 예제에서는 두 가지 메서드로 분할됩니다 AccessTheWebAsync
. 첫 번째 메서드는 AccessTheWebAsync
그룹에 대한 모든 다운로드 작업을 시작하고 표시 프로세스를 제어하도록 설정합니다 pendingWork
. 이 메서드는 LINQ 쿼리(언어 통합 쿼리) ToArray 를 사용하여 모든 다운로드 작업을 동시에 시작합니다.
AccessTheWebAsync
그런 다음 각 다운로드 완료를 기다리고 길이를 표시하기 위해 호출 FinishOneGroupAsync
합니다.
FinishOneGroupAsync
는 pendingWork
에 AccessTheWebAsync
에서 할당된 작업을 반환합니다. 이 값은 작업이 완료되기 전에 다른 작업에 의한 중단을 방지합니다.
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
FinishOneGroupAsync 메서드
이 메서드는 그룹의 다운로드 작업을 순환하여 각 작업을 기다리고, 다운로드한 웹 사이트의 길이를 표시하고, 합계에 길이를 추가합니다.
첫 번째 문장 FinishOneGroupAsync
은 pendingWork
을 사용하여 메서드를 입력하는 것이 이미 표시 프로세스에 있는 작업이나 이미 대기 중인 작업을 방해하지 않도록 합니다. 이러한 작업이 진행 중인 경우 입력 작업은 해당 순서를 기다려야 합니다.
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
앱 빌드의 코드에 변경 내용을 붙여넣어 이 예제를 실행하거나, 앱을 다운로드하는 지침에 따라 샘플을 다운로드한 다음 QueueResults 프로젝트를 실행할 수 있습니다.
관심 지점
출력에서 파운드 기호(#)로 시작하는 정보 줄은 이 예제의 작동 방식을 명확히 합니다.
출력은 다음 패턴을 보여 줍니다.
이전 그룹이 출력을 표시하는 동안 그룹을 시작할 수 있지만 이전 그룹의 출력 표시는 중단되지 않습니다.
#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: 915908
작업은 A 그룹,
pendingWork
Nothing
가장 먼저 시작된 그룹에 대해서만FinishOneGroupAsync
시작됩니다. 그룹 A는FinishOneGroupAsync
에 도달했을 때 아직 await 식을 완료하지 않았습니다. 따라서AccessTheWebAsync
에 대한 컨트롤이 반환되지 않았고,pendingWork
에 대한 첫 번째 할당이 발생하지 않았습니다.다음 두 줄은 항상 출력에 함께 표시됩니다. 그룹의 작업을
StartButton_Click
시작하고 그룹에 대한 작업을pendingWork
할당하는 동안 코드가 중단되지 않습니다.#Starting group B. #Task assigned for group B. Download tasks are active.
그룹이
StartButton_Click
에 들어가면, 작업이FinishOneGroupAsync
에 이를 때까지 await 식을 완료하지 않습니다. 따라서 해당 코드 세그먼트 동안 다른 작업을 제어할 수 없습니다.
예제 앱 검토 및 실행
예제 앱을 더 잘 이해하려면 앱을 구현하지 않고도 이 항목의 끝부분에 있는 코드를 다운로드하거나 직접 빌드하거나 검토할 수 있습니다.
비고
예제를 WPF(Windows Presentation Foundation) 데스크톱 앱으로 실행하려면 Visual Studio 2012 이상과 .NET Framework 4.5 이상이 컴퓨터에 설치되어 있어야 합니다.
앱 다운로드
Async Samples: .NET Desktop Apps의 재진입에서 압축된 파일을 다운로드합니다.
다운로드한 파일의 압축을 해제한 다음 Visual Studio를 시작합니다.
메뉴 모음에서 파일, 열기, 프로젝트/솔루션을 선택합니다.
압축 해제된 샘플 코드를 포함하는 폴더로 이동한 다음 솔루션(.sln) 파일을 엽니다.
솔루션 탐색기에서 실행하려는 프로젝트의 바로 가기 메뉴를 연 다음 StartUpProject로 설정을 선택합니다.
Ctrl+F5 키를 선택하여 프로젝트를 빌드하고 실행합니다.
앱 빌드
다음 섹션에서는 예제를 WPF 앱으로 빌드하는 코드를 제공합니다.
WPF 앱을 빌드하려면
Visual Studio를 시작합니다.
메뉴 모음에서 파일, 새로 만들기, 프로젝트를 선택합니다.
새 프로젝트 대화 상자가 열립니다.
설치된 템플릿 창에서 Visual Basic을 확장한 다음 Windows를 확장합니다.
프로젝트 형식 목록에서 WPF 애플리케이션을 선택합니다.
프로젝트
WebsiteDownloadWPF
이름을 지정하고 .NET Framework 버전 4.6 이상을 선택한 다음 확인 단추를 클릭합니다.새 프로젝트가 솔루션 탐색기에 나타납니다.
Visual Studio Code 편집기에서 MainWindow.xaml 탭을 선택합니다.
탭이 표시되지 않으면 솔루션 탐색기에서 MainWindow.xaml의 바로 가기 메뉴를 열고 코드 보기를 선택합니다.
MainWindow.xaml의 XAML 보기에서 코드를 다음 코드로 바꿉니다.
<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>
MainWindow.xaml의 디자인 보기에 텍스트 상자와 단추가 포함된 간단한 창이 나타납니다.
솔루션 탐색기에서 참조를 마우스 오른쪽 단추로 클릭하고 참조 추가를 선택합니다.
이미 선택되지 않았다면, System.Net.Http에 대한 참조를 추가하세요.
솔루션 탐색기에서 MainWindow.xaml.vb 대한 바로 가기 메뉴를 연 다음 코드 보기를 선택합니다.
MainWindow.xaml.vb 코드를 다음 코드로 바꿉다.
' 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 Class
Ctrl+F5 키를 선택하여 프로그램을 실행한 다음 시작 단추를 여러 번 선택합니다.
시작 버튼 사용 안 함, 작업 취소 및 다시 시작 또는 여러 작업 실행 및 출력 큐 대기를 통해 재진입을 처리하도록 변경합니다.
참고하십시오
.NET