WhenAny: .NET Framework와 Windows 런타임 간 브리징(C# 및 Visual Basic)
이 항목의 예제는 완료된 순서대로 비동기 작업을 처리하는 .NET Framework 메서드와 함께 블로그 피드를 비동기적으로 다운로드하는 Windows 런타임와 결합합니다. 형식에 대한 자세한 내용은 SyndicationClient를 참조하십시오. 메서드에 대한 자세한 내용은 Task.WhenAny을 참조하십시오.
이러한 기능을 결합하여 여러 블로그 피드를 동시에 다운로드하고 완료될 때 결과를 처리할 수 있습니다. 어떤 피드가 다른 피드보다 더 빠르게 다운로드되면 해당 결과가 먼저 나타납니다. SyndicationClient 메서드를 사용하면 더 쉽게 피드를 다운로드할 수 있으며, Task.WhenAny 메서드를 사용하면 다운로드를 끝낸 다음 피드를 쉽게 식별할 수 있습니다.
참고
예제를 실행하려면 컴퓨터에 Windows 8이 설치되어 있어야 합니다.또한 Visual Studio에서 예제를 실행하려면 Visual Studio 2012, Visual Studio 2013, Windows 8용 Visual Studio Express 2012 또는 Visual Studio Express 2013 for Windows가 설치되어 있어야 합니다.
다음 코드는 Windows 런타임 및 .NET Framework에서 이러한 특징을 결합합니다.
SyndicationClient.RetrieveFeedAsync는 블로그 피드를 다운로드하여 IAsyncOperationWithProgress 인스턴스를 반환합니다.
AsTask``2 확장 메서드는 IAsyncOperationWithProgress 인스턴스를 Task 인스턴스로 나타냅니다.
WhenAny``1 작업 컬렉션에서 완료 대기 중인 첫 번째 작업을 확인하는 태스크를 반환합니다.
Try
Dim feedsQuery As IEnumerable(Of Task(Of SyndicationFeed)) =
From uri In uriList
Select client.RetrieveFeedAsync(uri).AsTask()
' AsTask changes the returns from RetrieveFeedAsync into tasks.
' Run the query to start all the asynchronous processes.
Dim blogFeedTasksList As List(Of Task(Of SyndicationFeed)) = feedsQuery.ToList()
Dim feed As SyndicationFeed
' Repeat the following until there are no tasks left:
' - Grab the first one that finishes.
' - Retrieve the results from the task (what the return statement
' in RetrieveFeedAsync returns).
' - Remove the task from the list.
' - Display the results.
While blogFeedTasksList.Count > 0
Dim nextTask As Task(Of SyndicationFeed) = Await Task.WhenAny(blogFeedTasksList)
feed = Await nextTask
blogFeedTasksList.Remove(nextTask)
DisplayResults(feed)
End While
Catch ex As Exception
ResultsTextBox.Text =
"Page could not be loaded." & vbCrLf & "Exception: " & ex.ToString()
End Try
try
{
IEnumerable<Task<SyndicationFeed>> feedsQuery =
from uri in uriList
// AsTask changes the returns from RetrieveFeedAsync into tasks.
select client.RetrieveFeedAsync(uri).AsTask();
// Run the query to start all the asynchronous processes.
List<Task<SyndicationFeed>> blogFeedTasksList = feedsQuery.ToList();
SyndicationFeed feed;
// Repeat the following until no tasks remain:
// - Grab the first one that finishes.
// - Retrieve the results from the task (what the return statement
// in RetrieveFeedAsync returns).
// - Remove the task from the list.
// - Display the results.
while (blogFeedTasksList.Count > 0)
{
Task<SyndicationFeed> nextTask = await Task.WhenAny(blogFeedTasksList);
feed = await nextTask;
blogFeedTasksList.Remove(nextTask);
DisplayResults(feed);
}
}
catch (Exception ex)
{
ResultsTextBox.Text =
"Page could not be loaded.\n\r" + "Exception: " + ex.ToString();
}
예제에서는 다음 줄과 유사한 출력을 생성합니다. 각 블로그의 경우 블로그 제목 뒤에 블로그 게시물에 대한 제목과 날짜가 표시됩니다.
Developing for Windows
New blog for Windows 8 app developers, 5/1/2012 2:33:02 PM -07:00
Trigger-Start Services Recipe, 3/24/2011 2:23:01 PM -07:00
. . .
Countdown to PDC10, 10/26/2010 4:11:28 PM -07:00
Extreme Windows Blog
PDXLAN 20: “Epidemic” Custom PC by Jon Hansz, 7/30/2012 2:31:35 PM -07:00
Samsung Notebook Series 9: Taking Thin and Light to the Extreme, 7/23/2012 12:06:03 PM -07:00
. . .
AMD Unveils A-Series APUs, 6/13/2011 9:34:01 PM -07:00
Blogging Windows
Windows 8 has reached the RTM milestone, 8/1/2012 9:00:00 AM -07:00
Windows 8 will be available on…, 7/18/2012 1:09:00 PM -07:00
. . .
More buzz from BUILD – Developers get their devices!, 9/13/2011 7:47:57 PM -07:00
Springboard Series Blog
What to Expect in User Experience Virtualization Beta 2, 6/25/2012 11:03:27 PM -07:00
Introducing Microsoft BitLocker Administration 2.0 Beta, 6/12/2012 8:08:23 AM -07:00
. . .
The Springboard Series Visits Lima, Peru, 11/18/2011 5:27:37 AM -08:00
이 항목의 나머지 부분에서는 예제를 만드는 방법 및 작동 방식에 대해 설명합니다.
이 응용 프로그램을 실행하려면 컴퓨터에 Visual Studio 2012 및 Windows 8이 설치되어 있어야 합니다.
이 항목에는 다음 단원이 포함되어 있습니다.
- 예제에 대한 옵션 설정
- 시작 코드 이해
- 시작 코드 확장
- 시작 코드 다운로드
- 완성된 응용 프로그램 다운로드
- 시작 코드 빌드
- 완성된 응용 프로그램 빌드
- 관련 항목
예제에 대한 옵션 설정
이 예제는 블로그 뷰어를 기반으로 하며, 빠른 시작: 비동기 프로그래밍에 await 연산자 사용에 설명되어 있습니다. 그러나 이 항목의 시작 코드는 하나가 아닌 여러 블로그 피드를 다운로드합니다.
시작 코드는 Windows 런타임 기능을 사용하여 블로그 피드를 순차적으로 다운로드합니다. 즉, 블로그 피드가 URL 컬렉션에 나열된 순서대로 다운로드됩니다. 완성된 응용 프로그램은 .NET Framework에서 완료된 순서대로 블로그 피드를 다운로드 하기 위해 기능을 추가합니다.
다음과 같은 방법으로 예제 코드를 설정할 수 있습니다.
시작 코드
시작 코드 다운로드에서 지침을 따라 시작 코드를 다운로드할 수 있습니다.
Building the Starter Code의 지침을 따라 시작 코드를 만들 수 있습니다.
시작 코드 빌드로 스크롤하면 시작 코드를 구현하지 않고도 검토할 수 있습니다.
응용 프로그램이 완료되었습니다.
완성된 응용 프로그램 다운로드에서 지침을 따라 완료된 응용 프로그램을 다운로드할 수 있습니다.
Building the Finished App의 지침을 따라 응용 프로그램을 직접 빌드할 수 있습니다.
완성된 응용 프로그램 빌드로 스크롤하면 완성된 응용 프로그램을 구현하지 않고도 응용 프로그램을 검토할 수 있습니다.
Understanding the Starter Code 단원에서는 기본 솔루션의 주요 사항에 대해 설명합니다.
기초 코드 확장 섹션은 AsTask``2 및 Task.WhenAny을 추가하여 코드를 수정하는 방법을 보여줍니다.
시작 코드 이해
스타터 코드는 SyndicationClient 메서드인 RetrieveFeedAsync를 사용하여 URI 목록의 각 URI에서 블로그 피드를 다운로드합니다. 메서드를 호출할 때마다 진행 중인 비동기 작업을 나타내는 IAsyncOperationWithProgress 인스턴스가 반환됩니다. 대기 중 비동기 작업은 다운로드한 블로그 피드에 대한 정보가 포함된 SyndicationFeed 인스턴스를 만듭니다.
코드는 RetrieveFeedAsync를 URI 목록의 각 엔트리에 적용하는 쿼리를 정의합니다. 실행하면 쿼리가 IAsyncOperationWithProgress 인스턴스의 컬렉션을 반환합니다.
Dim feedsQuery As IEnumerable(Of IAsyncOperationWithProgress(Of SyndicationFeed,
RetrievalProgress)) =
From uri In uriList
Select client.RetrieveFeedAsync(uri)
IEnumerable<IAsyncOperationWithProgress<SyndicationFeed,
RetrievalProgress>> feedsQuery = from uri in uriList
select client.RetrieveFeedAsync(uri);
ToList``1은 다음 코드와 같이 쿼리를 실행하고 비동기 프로세스를 시작합니다.
Dim blogFeedOpsList As List(Of IAsyncOperationWithProgress(Of SyndicationFeed,
RetrievalProgress)) =
feedsQuery.ToList()
List<IAsyncOperationWithProgress<SyndicationFeed,
RetrievalProgress>> blogFeedOpsList = feedsQuery.ToList();
이 시점에는 활성 IAsyncOperationWithProgress 인스턴스 목록을 확인할 수 있습니다. 최종 결과를 얻으려면 각 인스턴스를 기다려야 합니다.
다음 루프는 각 IAsyncOperationWithProgress 인스턴스가 SyndicationFeed 결과를 검색할 때까지 기다립니다.
Dim feed As SyndicationFeed
For Each blogFeedOp In blogFeedOpsList
' The Await operator retrieves the final result (a SyndicationFeed instance)
' from each IAsyncOperation instance.
feed = Await blogFeedOp
DisplayResults(feed)
Next
SyndicationFeed feed;
foreach (var blogFeedOp in blogFeedOpsList)
{
// The await operator retrieves the final result (a SyndicationFeed instance)
// from each IAsyncOperation instance.
feed = await blogFeedOp;
DisplayResults(feed);
}
항목의 끝 부분에 있는 시작 코드 빌드 섹션에서 이 프로그램 버전을 검토할 수 있습니다.
빠른 시작: 비동기 프로그래밍에 await 연산자 사용에서 비동기 Windows 런타임 API를 이용한 프로그래밍에 대해 자세한 내용을 볼 수 있습니다.
시작 코드 확장
시작 코드는 SyndicationClient를 사용하여 블로그 피드를 쉽게 다운로드할 수 있음을 보여줍니다. 예제를 완료하는 데 남은 단계는 해당 다운로드가 URI 목록에 표시되는 순서 대신 완료되는 순서로 응용 프로그램이 블로그 피드를 처리하도록 설정하는 것입니다.
기능 향상을 달성하는 키는 Task.WhenAny 메서드입니다. WhenAny를 비동기 프로세스 컬렉션에 적용하면 메서드는 대기 시간을 최소화하며 완료된 첫 번째 프로세스를 반환합니다. 이 예제에서 블로그 피드 정보가 표시되는 순서는 중요하지 않습니다. 어떤 다운로드가 느린 경우에는 다른 블로그의 결과가 먼저 표시될 수 있습니다. WhenAny에 작업의 컬렉션이 필요하다는 점을 제외하고, WhenAny에 완벽한 상황입니다.
AsTask 호출
WhenAny에서는 Task 또는 Task 인스턴스가 필요하지만, 블로그 피드를 다운로드하는 SyndicationClient 메서드는 IAsyncOperationWithProgress 인스턴스를 다운로드합니다. 따라서 앱이 Windows 런타임의 IAsyncOperationWithProgress 개체와 .NET Framework의 Task 개체 사이를 연결해야 합니다.
.NET Framework는 전환을 위해 AsTask``2 확장 메서드를 제공합니다. IAsyncOperationWithProgress 인스턴스에서 AsTask를 호출하면 AsTask에서 비동기 작업을 나타내는 작업을 반환합니다. 해당 IAsyncOperationWithProgress 인스턴스가 완료되면 작업이 완료되고 작업에 인스턴스의 결과 또는 예외가 포함됩니다.
따라서 다음 코드와 같이 RetrieveFeedAsync에서 반환하는 각 IAsyncOperationWithProgress 인스턴스에서 AsTask를 방금 호출했습니다. 이 코드는 변수 이름을 변경하여 변경 내용을 작업에 반영하고 명확함을 위해 명시적 입력을 사용합니다.
Dim feedsQuery As IEnumerable(Of Task(Of SyndicationFeed)) =
From uri In uriList
Select client.RetrieveFeedAsync(uri).AsTask()
' AsTask changes the returns from RetrieveFeedAsync into tasks.
' Run the query to start all the asynchronous processes.
Dim blogFeedTasksList As List(Of Task(Of SyndicationFeed)) = feedsQuery.ToList()
IEnumerable<Task<SyndicationFeed>> feedsQuery =
from uri in uriList
// AsTask changes the returns from RetrieveFeedAsync into tasks.
select client.RetrieveFeedAsync(uri).AsTask();
// Run the query to start all the asynchronous processes.
List<Task<SyndicationFeed>> blogFeedTasksList = feedsQuery.ToList();
참고
AsTask는 사용자가 모르는 비동기 프로그래밍에서 중요한 역할을 합니다.컴파일러는 다음 코드와 같이 await 연산자를 IAsyncAction 또는 IAsyncOperation 인스턴스에 적용할 때마다 AsTask를 사용합니다.
' What you write. Dim feed As SyndicationFeed = Await client.RetrieveFeedAsync(feedUri) ' What the compiler does. ' Dim feed As SyndicationFeed = Await client.RetrieveFeedAsync(feedUri).AsTask()
// What you write. SyndicationFeed feed = await client.RetrieveFeedAsync(feedUri); // What the compiler does. //SyndicationFeed feed = await client.RetrieveFeedAsync(feedUri).AsTask();
WhenAny 적용
변환의 마지막 단계는 Task.WhenAny 메서드를 응용 프로그램에 추가하는 것입니다. WhenAny는 작업 컬렉션(blogFeedTasksList)에 적용되고 완료되면 컬렉션의 첫 번째 작업을 반환합니다. 구체적으로, WhenAny는 대기할 때 가장 먼저 완료되는 작업으로 확인되는 작업을 반환합니다.
다음 문은 WhenAny를 호출하고 결과를 기다립니다. 이 코드는 결과를 더 명확히 표시하기 위해 명시적 입력을 사용합니다.
Dim nextTask As Task(Of SyndicationFeed) = Await Task.WhenAny(blogFeedTasksList)
Task<SyndicationFeed> nextTask = await Task.WhenAny(blogFeedTasksList);
다음의 코드는 이전 상태와 동일한 작업을 수행하지만 어떤 일이 발생하는지 명확히 하기 위해 두 상태로의 작업을 중단합니다. 첫 번째 문은 WhenAny를 호출하며, 두 번째 문은 결과를 기다립니다.
' WhenAny returns a task that, when awaited, produces a task.
' Call:
Dim whenAnyTask As Task(Of Task(Of SyndicationFeed)) = Task.WhenAny(blogFeedTasksList)
' Await:
Dim nextTask As Task(Of SyndicationFeed) = Await whenAnyTask
// WhenAny returns a task that, when awaited, produces a task.
// Call:
Task<Task<SyndicationFeed>> whenAnyTask = Task.WhenAny(blogFeedTasksList);
// Await:
Task<SyndicationFeed> nextTask = await whenAnyTask;
마지막으로, nextTask를 기다려 처음에 완료한 작업에서 결과(SyndicationFeed 인스턴스)를 검색한 다음, 다시 처리할 필요가 없도록 목록에서 nextTask를 제거해야 합니다.
feed = Await nextTask
blogFeedTasksList.Remove(nextTask)
feed = await nextTask;
blogFeedTasksList.Remove(nextTask);
blogFeedTasksList의 각 단계에 이러한 단계를 실행하는 while 루프를 사용합니다.
While blogFeedTasksList.Count > 0
Dim nextTask As Task(Of SyndicationFeed) = Await Task.WhenAny(blogFeedTasksList)
feed = Await nextTask
blogFeedTasksList.Remove(nextTask)
DisplayResults(feed)
End While
while (blogFeedTasksList.Count > 0)
{
Task<SyndicationFeed> nextTask = await Task.WhenAny(blogFeedTasksList);
feed = await nextTask;
blogFeedTasksList.Remove(nextTask);
DisplayResults(feed);
}
항목의 끝 부분에 있는 완성된 응용 프로그램 빌드 섹션에서 이 프로그램 버전을 검토할 수 있습니다. 또는 Downloading the Finished App의 지침을 따라 프로젝트를 다운로드할 수 있습니다.
경고
소규모 작업이 포함된 문제의 경우 예제에 설명된 것처럼 루프에 WhenAny를 사용하는 것이 좋습니다.그러나 처리할 작업 수가 많으면 다른 방법이 더 효율적입니다.자세한 내용 및 예제를 보려면 Processing Tasks as they complete를 참조하십시오.
시작 코드 다운로드
비동기 샘플: .NET에서 Windows로 연결에서 시작 코드 예제를 다운로드할 수 있습니다. 인터넷에 액세스할 수 없는 경우 이 항목의 뒷부분에 있는 시작 코드 빌드의 지침에 따라 시작 코드를 만듭니다.
코드를 다운로드한 후 다음 단계를 수행하여 열고 실행합니다.
다운로드한 파일을 압축한 다음 Visual Studio 2012를 시작합니다.
메뉴 모음에서 파일, 열기, 프로젝트/솔루션을 선택합니다.
비압축된 샘플 코드를 보관하는 폴더로 이동하고 AsTaskWhenAnyDemoVB 또는 AsTaskWhenAnyDemoCS에 위한 솔루션 파일(.sln)을 엽니다.
솔루션 탐색기에서 SequentialBlogReader 프로젝트에 대한 바로 가기 메뉴를 연 후 시작 프로젝트로 설정을 선택합니다.
프로젝트를 빌드하고 실행하려면 F5 키를 선택합니다.
코드를 여러 번 실행하여 결과가 매번 동일한 순서로 나타나는지 확인합니다.
항목의 끝 부분에 있는 시작 코드 빌드 섹션에서 MainPage.xaml.vb 또는 MainPage.xaml.cs 파일을 검토할 수 있습니다.
이 예제는 블로그 뷰어를 기반으로 하며, 빠른 시작: 비동기 프로그래밍에 await 연산자 사용에 설명되어 있습니다. 그러나 이 항목의 시작 코드는 하나가 아닌 여러 블로그 피드를 다운로드합니다.
응용 프로그램에 대해 수행할 수 있는 다양한 개선 내용과 확장에 대한 자세한 내용은 블로그 뷰어 만들기를 참조하십시오.
완성된 응용 프로그램 다운로드
예제를 직접 빌드하지 않을 경우 전체 예제를 다운로드할 수 있습니다. 시작 코드 다운로드 단원의 지침을 따르되 WhenAnyBlogReader를 시작 프로젝트로 선택하십시오.
프로그램을 여러 번 실행하여 블로그 피드가 다른 순서로 나타나는지 확인합니다.
항목의 끝 부분에 있는 완성된 응용 프로그램 빌드에서 MainPage.xaml.vb 또는 MainPage.xaml.cs 파일을 검토할 수 있습니다.
시작 코드 빌드
비동기 샘플: .NET에서 Windows로 연결에서 이 항목의 예제를 다운로드할 수 있습니다. 응용 프로그램을 직접 설정하려는 경우 다음 단계를 수행합니다.
Visual Studio 2012를 시작합니다.
메뉴 모음에서 파일, 새로 만들기, 프로젝트를 선택합니다.
새 프로젝트 대화 상자가 열립니다.
설치됨의 템플릿 범주에서 Visual Basic 또는 **Visual C#**을 선택한 다음 프로젝트 형식 목록에서 Windows 스토어를 선택합니다.
프로젝트 형식 목록에서 **새 응용 프로그램(XAML)**을 선택합니다.
프로젝트 SequentialBlogReader의 이름을 지정한 다음 확인 단추를 선택합니다.
솔루션 탐색기에 새 프로젝트가 나타납니다.
솔루션 탐색기에서 MainPage.xaml의 바로 가기 메뉴를 열고 열기를 선택합니다.
MainPage.xaml의 XAML 창에서 코드를 다음 코드로 바꿉니다.
<Page x:Class="SequentialBlogReader.MainPage" xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="using:AsTaskWhenAnyDemo" xmlns:d="https://schemas.microsoft.com/expression/blend/2008" xmlns:mc="https://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d"> <Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}"> <Button x:Name="StartButton" Content="Start" HorizontalAlignment="Stretch" Margin="325,128,330,0" VerticalAlignment="Top" Click="StartButton_Click" Height="71" Background="#FFA89B9B" FontWeight="Bold" FontSize="36"/> <TextBox x:Name="ResultsTextBox" Margin="325,222,330,0" TextWrapping="Wrap" VerticalAlignment="Top" Height="546" FontSize="10" ScrollViewer.VerticalScrollBarVisibility="Visible" /> </Grid> </Page>
텍스트 상자 및 단추가 포함된 간단한 창이 MainPage.xaml의 디자인 창에 나타납니다.
UI에 대해 수행할 수 있는 다양한 개선 내용과 확장에 대한 자세한 내용은 블로그 뷰어 만들기를 참조하십시오.
솔루션 탐색기에서 MainPage.xaml.vb 또는 MainPage.xaml.cs의 바로 가기 메뉴를 열고 코드 보기를 선택합니다.
MainPage.xaml.vb 또는 MainPage.xaml.cs의 코드를 다음 코드로 바꿉니다.
' Add an Imports statement for SyndicationClient. Imports Windows.Web.Syndication ' The Blank Page item template is documented at http:'go.microsoft.com/fwlink/?LinkId=234238 Public NotInheritable Class MainPage Inherits Page Protected Overrides Sub OnNavigatedTo(e As Navigation.NavigationEventArgs) End Sub ' The async modifier enables you to use await in the event handler. Private Async Sub StartButton_Click(sender As Object, e As RoutedEventArgs) ResultsTextBox.Text = "" ' Disable the button until the operation is complete. StartButton.IsEnabled = False Dim client As Windows.Web.Syndication.SyndicationClient = New SyndicationClient() ' Force the SyndicationClient to download the information. client.BypassCacheOnRetrieve = True Dim uriList = CreateUriList() Try Dim feedsQuery As IEnumerable(Of IAsyncOperationWithProgress(Of SyndicationFeed, RetrievalProgress)) = From uri In uriList Select client.RetrieveFeedAsync(uri) ' Run the query to start all the asynchronous processes. Dim blogFeedOpsList As List(Of IAsyncOperationWithProgress(Of SyndicationFeed, RetrievalProgress)) = feedsQuery.ToList() Dim feed As SyndicationFeed For Each blogFeedOp In blogFeedOpsList ' The Await operator retrieves the final result (a SyndicationFeed instance) ' from each IAsyncOperation instance. feed = Await blogFeedOp DisplayResults(feed) Next Catch ex As Exception ResultsTextBox.Text = "Page could not be loaded." & vbCrLf & "Exception: " & ex.ToString() End Try ' Reenable the button in case you want to run the operation again. StartButton.IsEnabled = True End Sub Function CreateUriList() As List(Of Uri) ' Create a list of URIs. Dim uriList = New List(Of Uri) From { New Uri("https://windowsteamblog.com/windows/b/developers/atom.aspx"), New Uri("https://windowsteamblog.com/windows/b/extremewindows/atom.aspx"), New Uri("https://windowsteamblog.com/windows/b/bloggingwindows/atom.aspx"), New Uri("https://windowsteamblog.com/windows/b/springboard/atom.aspx") } Return uriList End Function Sub DisplayResults(sf As SyndicationFeed) ' Title of the blog. ResultsTextBox.Text &= sf.Title.Text & vbCrLf ' Titles and dates for blog posts. For Each item As SyndicationItem In sf.Items ResultsTextBox.Text &= vbTab & item.Title.Text & ", " & item.PublishedDate.ToString() & vbCrLf Next ResultsTextBox.Text &= vbCrLf End Sub End Class
using System; using System.Collections.Generic; using System.IO; using System.Linq; using Windows.Foundation; using Windows.Foundation.Collections; using Windows.UI.Xaml; using Windows.UI.Xaml.Controls; using Windows.UI.Xaml.Controls.Primitives; using Windows.UI.Xaml.Data; using Windows.UI.Xaml.Input; using Windows.UI.Xaml.Media; using Windows.UI.Xaml.Navigation; // Add a using directive for SyndicationClient. using Windows.Web.Syndication; namespace SequentialBlogReader { public sealed partial class MainPage : Page { public MainPage() { this.InitializeComponent(); } protected override void OnNavigatedTo(NavigationEventArgs e) { } private async void StartButton_Click(object sender, RoutedEventArgs e) { ResultsTextBox.Text = ""; // Disable the button until the operation is complete. StartButton.IsEnabled = false; Windows.Web.Syndication.SyndicationClient client = new SyndicationClient(); // Force the SyndicationClient to download the information. client.BypassCacheOnRetrieve = true; var uriList = CreateUriList(); try { IEnumerable<IAsyncOperationWithProgress<SyndicationFeed, RetrievalProgress>> feedsQuery = from uri in uriList select client.RetrieveFeedAsync(uri); // Run the query to start all the asynchronous processes. List<IAsyncOperationWithProgress<SyndicationFeed, RetrievalProgress>> blogFeedOpsList = feedsQuery.ToList(); SyndicationFeed feed; foreach (var blogFeedOp in blogFeedOpsList) { // The await operator retrieves the final result (a SyndicationFeed instance) // from each IAsyncOperation instance. feed = await blogFeedOp; DisplayResults(feed); } } catch (Exception ex) { ResultsTextBox.Text = "Page could not be loaded.\n\r" + "Exception: " + ex.ToString(); } // Reenable the button in case you want to run the operation again. StartButton.IsEnabled = true; } List<Uri> CreateUriList() { // Create a list of URIs. List<Uri> uriList = new List<Uri> { new Uri("https://windowsteamblog.com/windows/b/developers/atom.aspx"), new Uri("https://windowsteamblog.com/windows/b/extremewindows/atom.aspx"), new Uri("https://windowsteamblog.com/windows/b/bloggingwindows/atom.aspx"), new Uri("https://windowsteamblog.com/windows/b/springboard/atom.aspx") }; return uriList; } void DisplayResults(SyndicationFeed sf) { // Title of the blog. ResultsTextBox.Text += sf.Title.Text + "\r\n"; // Titles and dates for blog posts. foreach (SyndicationItem item in sf.Items) { ResultsTextBox.Text += "\t" + item.Title.Text + ", " + item.PublishedDate.ToString() + "\r\n"; } ResultsTextBox.Text += "\r\n"; } } }
F5 키를 선택하여 프로그램을 실행한 다음 시작 단추를 선택합니다.
완성된 응용 프로그램 빌드
비동기 샘플: .NET에서 Windows로 연결에서 이 항목의 예제를 다운로드할 수 있습니다. 응용 프로그램을 직접 설정하려는 경우 다음 단계를 수행합니다.
Visual Studio 2012를 시작합니다.
메뉴 모음에서 파일, 새로 만들기, 프로젝트를 선택합니다.
새 프로젝트 대화 상자가 열립니다.
설치됨의 템플릿 범주에서 Visual Basic 또는 **Visual C#**을 선택한 다음 Windows 스토어를 선택합니다.
프로젝트 형식 목록에서 **새 응용 프로그램(XAML)**을 선택합니다.
프로젝트 WhenAnyBlogReader의 이름을 지정한 다음 확인 단추를 선택합니다.
솔루션 탐색기에 새 프로젝트가 나타납니다.
솔루션 탐색기에서 MainPage.xaml의 바로 가기 메뉴를 열고 열기를 선택합니다.
MainPage.xaml의 XAML 창에서 코드를 다음 코드로 바꿉니다.
<Page x:Class="WhenAnyBlogReader.MainPage" xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="using:AsTaskWhenAnyDemo" xmlns:d="https://schemas.microsoft.com/expression/blend/2008" xmlns:mc="https://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d"> <Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}"> <Button x:Name="StartButton" Content="Start" HorizontalAlignment="Stretch" Margin="325,128,330,0" VerticalAlignment="Top" Click="StartButton_Click" Height="71" Background="#FFA89B9B" FontWeight="Bold" FontSize="36"/> <TextBox x:Name="ResultsTextBox" Margin="325,222,330,0" TextWrapping="Wrap" VerticalAlignment="Top" Height="546" FontSize="10" ScrollViewer.VerticalScrollBarVisibility="Visible" /> </Grid> </Page>
텍스트 상자 및 단추가 포함된 간단한 창이 MainPage.xaml의 디자인 창에 나타납니다.
응용 프로그램에 대해 수행할 수 있는 다양한 개선 내용과 확장에 대한 자세한 내용은 블로그 뷰어 만들기를 참조하십시오.
솔루션 탐색기에서 MainPage.xaml.vb 또는 MainPage.xaml.cs의 바로 가기 메뉴를 열고 코드 보기를 선택합니다.
MainPage.xaml.vb 또는 MainPage.xaml.cs의 코드를 다음 코드로 바꿉니다.
' Add an Imports statement for SyndicationClient. Imports Windows.Web.Syndication ' Add an Imports statement for the Tasks. Imports System.Threading.Tasks ' The Blank Page item template is documented at http:'go.microsoft.com/fwlink/?LinkId=234238 Public NotInheritable Class MainPage Inherits Page Protected Overrides Sub OnNavigatedTo(e As Navigation.NavigationEventArgs) End Sub Private Async Sub StartButton_Click(sender As Object, e As RoutedEventArgs) ResultsTextBox.Text = "" ' Disable the button until the operation is complete. StartButton.IsEnabled = False Dim client As Windows.Web.Syndication.SyndicationClient = New SyndicationClient() ' Force the SyndicationClient to download the information. client.BypassCacheOnRetrieve = True Dim uriList = CreateUriList() ' The following code avoids the use of implicit typing so that you ' can see the types clearly. Try Dim feedsQuery As IEnumerable(Of Task(Of SyndicationFeed)) = From uri In uriList Select client.RetrieveFeedAsync(uri).AsTask() ' AsTask changes the returns from RetrieveFeedAsync into tasks. ' Run the query to start all the asynchronous processes. Dim blogFeedTasksList As List(Of Task(Of SyndicationFeed)) = feedsQuery.ToList() Dim feed As SyndicationFeed ' Repeat the following until there are no tasks left: ' - Grab the first one that finishes. ' - Retrieve the results from the task (what the return statement ' in RetrieveFeedAsync returns). ' - Remove the task from the list. ' - Display the results. While blogFeedTasksList.Count > 0 Dim nextTask As Task(Of SyndicationFeed) = Await Task.WhenAny(blogFeedTasksList) feed = Await nextTask blogFeedTasksList.Remove(nextTask) DisplayResults(feed) End While Catch ex As Exception ResultsTextBox.Text = "Page could not be loaded." & vbCrLf & "Exception: " & ex.ToString() End Try ' Reenable the button in case you want to run the operation again. StartButton.IsEnabled = True End Sub Function CreateUriList() As List(Of Uri) ' Create a list of URIs. Dim uriList = New List(Of Uri) From { New Uri("https://windowsteamblog.com/windows/b/developers/atom.aspx"), New Uri("https://windowsteamblog.com/windows/b/extremewindows/atom.aspx"), New Uri("https://windowsteamblog.com/windows/b/bloggingwindows/atom.aspx"), New Uri("https://windowsteamblog.com/windows/b/springboard/atom.aspx") } Return uriList End Function Sub DisplayResults(sf As SyndicationFeed) ' Title of the blog. ResultsTextBox.Text &= sf.Title.Text & vbCrLf ' Titles and dates for blog posts. For Each item As SyndicationItem In sf.Items ResultsTextBox.Text &= vbTab & item.Title.Text & ", " & item.PublishedDate.ToString() & vbCrLf Next ResultsTextBox.Text &= vbCrLf End Sub End Class
using System; using System.Collections.Generic; using System.IO; using System.Linq; using Windows.Foundation; using Windows.Foundation.Collections; using Windows.UI.Xaml; using Windows.UI.Xaml.Controls; using Windows.UI.Xaml.Controls.Primitives; using Windows.UI.Xaml.Data; using Windows.UI.Xaml.Input; using Windows.UI.Xaml.Media; using Windows.UI.Xaml.Navigation; // Add a using directive for SyndicationClient. using Windows.Web.Syndication; // Add a using directive for the Tasks. using System.Threading.Tasks; namespace WhenAnyBlogReader { public sealed partial class MainPage : Page { public MainPage() { this.InitializeComponent(); } protected override void OnNavigatedTo(NavigationEventArgs e) { } private async void StartButton_Click(object sender, RoutedEventArgs e) { ResultsTextBox.Text = ""; // Disable the button until the operation is complete. StartButton.IsEnabled = false; Windows.Web.Syndication.SyndicationClient client = new SyndicationClient(); // Force the SyndicationClient to download the information. client.BypassCacheOnRetrieve = true; var uriList = CreateUriList(); // The following code avoids the use of implicit typing (var) so that you // can identify the types clearly. try { IEnumerable<Task<SyndicationFeed>> feedsQuery = from uri in uriList // AsTask changes the returns from RetrieveFeedAsync into tasks. select client.RetrieveFeedAsync(uri).AsTask(); // Run the query to start all the asynchronous processes. List<Task<SyndicationFeed>> blogFeedTasksList = feedsQuery.ToList(); SyndicationFeed feed; // Repeat the following until no tasks remain: // - Grab the first one that finishes. // - Retrieve the results from the task (what the return statement // in RetrieveFeedAsync returns). // - Remove the task from the list. // - Display the results. while (blogFeedTasksList.Count > 0) { Task<SyndicationFeed> nextTask = await Task.WhenAny(blogFeedTasksList); feed = await nextTask; blogFeedTasksList.Remove(nextTask); DisplayResults(feed); } } catch (Exception ex) { ResultsTextBox.Text = "Page could not be loaded.\n\r" + "Exception: " + ex.ToString(); } // Reenable the button in case you want to run the operation again. StartButton.IsEnabled = true; } List<Uri> CreateUriList() { // Create a list of URIs. List<Uri> uriList = new List<Uri> { new Uri("https://windowsteamblog.com/windows/b/developers/atom.aspx"), new Uri("https://windowsteamblog.com/windows/b/extremewindows/atom.aspx"), new Uri("https://windowsteamblog.com/windows/b/bloggingwindows/atom.aspx"), new Uri("https://windowsteamblog.com/windows/b/springboard/atom.aspx") }; return uriList; } void DisplayResults(SyndicationFeed sf) { // Title of the blog. ResultsTextBox.Text += sf.Title.Text + "\r\n"; // Titles and dates for blog posts. foreach (SyndicationItem item in sf.Items) { ResultsTextBox.Text += "\t" + item.Title.Text + ", " + item.PublishedDate.ToString() + "\r\n"; } ResultsTextBox.Text += "\r\n"; } } }
F5 키를 선택하여 프로그램을 실행한 다음 시작 단추를 선택합니다.
참고 항목
참조
개념
Async 및 Await를 사용한 비동기 프로그래밍(C# 및 Visual Basic)
비동기 작업 하나가 완료되면 남은 비동기 작업 취소(C# 및 Visual Basic)
비동기 작업을 여러 개 시작하고 완료될 때마다 처리(C# 및 Visual Basic)