共用方式為


取消作業:銜接 .NET Framework 和 Windows 執行階段 (C# 和 Visual Basic)

您可以結合 .NET Framework 與 Windows 執行階段中功能讓您的資源。本主題中的範例示範如何使用 .NET FrameworkCancellationToken 執行個體將取消按鈕設定為使用 Windows 執行階段 方法下載從網路的網誌饋送的應用程式。

注意事項注意事項

若要執行這個範例,必須在電腦上安裝 Windows 8。此外,因此,如果您要從 Visual Studio 執行這個範例,您也必須在 Visual Studio 2012 已安裝或 Visual Studio Express 2012 for Windows 8

AsTask 提供橋接器

取消語彙基元要求 Task 執行個體,不過, Windows 執行階段 方法產生 IAsyncOperationWithProgress 執行個體。您可以使用 .NET Framework AsTask 擴充方法橋接這兩者。

在此範例中的 DownloadBlogsAsync 方法完成大部分的工作。

Async Function DownloadBlogsAsync(ct As CancellationToken) As Task
    Dim client As Windows.Web.Syndication.SyndicationClient = New SyndicationClient()

    Dim uriList = CreateUriList()

    ' Force the SyndicationClient to download the information.
    client.BypassCacheOnRetrieve = True


    ' The following code avoids the use of implicit typing (var) so that you 
    ' can identify the types clearly.

    For Each uri In uriList
        ' ***These three lines are combined in the single statement that follows them.
        'Dim feedOp As IAsyncOperationWithProgress(Of SyndicationFeed, RetrievalProgress) =
        '    client.RetrieveFeedAsync(uri)
        'Dim feedTask As Task(Of SyndicationFeed) = feedOp.AsTask(ct)
        'Dim feed As SyndicationFeed = Await feedTask

        ' ***You can combine the previous three steps in one expression.
        Dim feed As SyndicationFeed = Await client.RetrieveFeedAsync(uri).AsTask(ct)

        DisplayResults(feed, ct)
    Next
End Function
async Task DownloadBlogsAsync(CancellationToken ct)
{
    Windows.Web.Syndication.SyndicationClient client = new SyndicationClient();

    var uriList = CreateUriList();

    // Force the SyndicationClient to download the information.
    client.BypassCacheOnRetrieve = true;

    // The following code avoids the use of implicit typing (var) so that you 
    // can identify the types clearly.

    foreach (var uri in uriList)
    {
        // ***These three lines are combined in the single statement that follows them.
        //IAsyncOperationWithProgress<SyndicationFeed, RetrievalProgress> feedOp = 
        //    client.RetrieveFeedAsync(uri);
        //Task<SyndicationFeed> feedTask = feedOp.AsTask(ct);
        //SyndicationFeed feed = await feedTask;

        // ***You can combine the previous three steps in one expression.
        SyndicationFeed feed = await client.RetrieveFeedAsync(uri).AsTask(ct);

        DisplayResults(feed);
    }
}

在迴圈的註解的部分詳細顯示轉換步驟。

  • 要啟動的 SyndicationClient.RetrieveFeedAsync 呼叫下載從指定的 URI 建立部落格摘要的非同步作業。非同步作業是 IAsyncOperationWithProgress 的執行個體。

    Dim feedOp As IAsyncOperationWithProgress(Of SyndicationFeed, RetrievalProgress) = 
        client.RetrieveFeedAsync(uri)
    
    IAsyncOperationWithProgress<SyndicationFeed, RetrievalProgress> feedOp =  
        client.RetrieveFeedAsync(uri);
    
  • 由於您要使用的 .NET Framework 的取消功能要求工作,程式碼會將 AsTask 表示 IAsyncOperationWithProgress 執行個體為 Task<TResult>。特別是,應用程式碼接受 CancellationToken 引數的 AsTask 多載。

    Dim feedTask As Task(Of SyndicationFeed) = feedOp.AsTask(ct)
    
    Task<SyndicationFeed> feedTask = feedOp.AsTask(ct);
    
  • 最後, await 或 Await 運算子等候工作 SyndicationFeed 會擷取結果。

    Dim feed As SyndicationFeed = Await feedTask
    
    SyndicationFeed feed = await feedTask;
    

如需 AsTask,請參閱 WhenAny:銜接 .NET Framework 和 Windows 執行階段 (C# 和 Visual Basic)中的 擴充起始程式碼

問題值得注意

您可以檢閱整個範例會移動到本主題結尾,透過下載這個範例至本機電腦,或是建立範例。如需詳細資訊和指示,請參閱 設定範例

因為您檢閱這個範例中,您將注意重點強調星號。我們建議您閱讀本節進一步了解這些點,,特別是如果您之前尚未使用 CancellationToken 。

若要實作取消按鈕,您的程式碼必須包含下列項目。

  • CancellationTokenSource 變數,則為 cts,在所有方法的範圍存取它。

    Public NotInheritable Class MainPage
        Inherits Page
    
        ' ***Declare a System.Threading.CancellationTokenSource.
        Dim cts As CancellationTokenSource
    
    
    public sealed partial class MainPage : Page
    {
        // ***Declare a System.Threading.CancellationTokenSource.
        CancellationTokenSource cts;
    
  • [移除] 按鈕的事件處理常式。事件處理常式會使用 CancellationTokenSource.Cancel 方法告知 cts ,當使用者要求取消。

    ' ***Add an event handler for the Cancel button.
    Private Sub cancelButton_Click(sender As Object, e As RoutedEventArgs)
        If cts IsNot Nothing Then
            cts.Cancel()
            ResultsTextBox.Text &= vbCrLf & "Downloads canceled by the Cancel button."
        End If
    End Sub
    
    // ***Add an event handler for the Cancel button.
    private void CancelButton_Click(object sender, RoutedEventArgs e)
    {
        if (cts != null)
        {
            cts.Cancel();
            ResultsTextBox.Text += "\r\nDownloads canceled by the Cancel button.";
        }
    }
    
  • [啟動] 按鈕的 StartButton_Click,這個事件的事件處理常式,包括下列動作。

    • 事件處理常式執行個體化 CancellationTokenSource,否則為 cts。

      cts = New CancellationTokenSource()
      
      // ***Instantiate the CancellationTokenSource.
      cts = new CancellationTokenSource();
      
    • 在對 DownloadBlogsAsync的呼叫,下載網誌饋送,程式碼將 ctsCancellationTokenSource.Token 屬性做為引數。如果要求取消, Token 屬性傳播訊息。

      Await DownloadBlogsAsync(cts.Token)
      
      await DownloadBlogsAsync(cts.Token);
      
    • 對 DownloadBlogsAsync 的呼叫中包含之 OperationCanceledException 的 catch 區塊結果的 try-catch 陳述式上,當您選取 [移除] 按鈕時。非同步方法的呼叫端定義採取什麼動作。這個範例會顯示訊息。

      下列程式碼會顯示完整的 try-catch 陳述式。

      Try
          ' ***Send a token to carry the message if cancellation is requested.
          Await DownloadBlogsAsync(cts.Token)
      
          ' ***Check for cancellations.
      Catch op As OperationCanceledException
          ' In practice, this catch block often is empty. It is used to absorb
          ' the exception,
          ResultsTextBox.Text &= vbCrLf & "Cancellation exception bubbles up to the caller."
      
          ' Check for other exceptions.
      Catch ex As Exception
          ResultsTextBox.Text =
              "Page could not be loaded." & vbCrLf & "Exception: " & ex.ToString()
      End Try
      
      try
      {
          // ***Send a token to carry the message if cancellation is requested.
          await DownloadBlogsAsync(cts.Token);
      }
      // ***Check for cancellations.
      catch (OperationCanceledException)
      {
          // In practice, this catch block often is empty. It is used to absorb
          // the exception,
          ResultsTextBox.Text += "\r\nCancellation exception bubbles up to the caller.";
      }
      // Check for other exceptions.
      catch (Exception ex)
      {
          ResultsTextBox.Text =
              "Page could not be loaded.\r\n" + "Exception: " + ex.ToString();
      }
      
  • 如先前所述本主題中, DownloadBlogsAsync 方法會呼叫 Windows 執行階段 方法,則為 RetrieveFeedAsync,並將 .NET Framework 擴充方法,則為 AsTask,則傳回的 IAsyncOperation 執行個體。AsTask 表示執行個體做為 Task,因此,您可以將取消語彙基元到非同步作業。請選擇 [移除] 按鈕時,語彙基元會傳送訊息。

    請注意使用,則為 AsTask,程式碼可以將相同的 CancellationToken 執行個體加入至 Windows 執行階段 方法 (RetrieveFeedAsync) 和 .NET Framework 方法 (DownloadBlogsAsync)。

    下列程式碼行顯示程式碼的這個部分。

    Dim feed As SyndicationFeed = Await client.RetrieveFeedAsync(uri).AsTask(ct)
    
    SyndicationFeed feed = await client.RetrieveFeedAsync(uri).AsTask(ct);
    
  • 如果您無法移除應用程式,它會產生下列輸出。

    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
        Windows Restart and Recovery Recipe, 3/21/2011 2:13:24 PM -07:00
    
    Extreme Windows Blog
        Samsung Series 9 27” PLS Display: Amazing Picture, 8/20/2012 2:41:48 PM -07:00
        NVIDIA GeForce GTX 660 Ti Graphics Card: Affordable Graphics Powerhouse, 8/16/2012 10:56:19 AM -07:00
        HP Z820 Workstation: Rising To the Challenge, 8/14/2012 1:57:01 PM -07:00
    
    Blogging Windows
        Windows Upgrade Offer Registration Now Available, 8/20/2012 1:01:00 PM -07:00
        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
    
    Windows for your Business
        What Windows 8 RTM Means for Businesses, 8/1/2012 9:01:00 AM -07:00
        Higher-Ed Learning with Windows 8, 7/26/2012 12:03:00 AM -07:00
        Second Public Beta of App-V 5.0 Now Available with Office Integration, 7/24/2012 10:07:26 AM -07:00
    
    Windows Experience Blog
        Tech Tuesday Live Twitter Chat with Microsoft Hardware, 8/20/2012 2:20:57 AM -07:00
        New Colors and New Artist Series Mice from Microsoft Hardware, 8/15/2012 12:06:35 AM -07:00
        Tech Tuesday Live Twitter Chat with HP on Keeping Kids Safe as They Head Back to School #winchat, 8/13/2012 12:24:18 PM -07:00
    
    Windows Security Blog
        Dealing with Fake Tech Support & Phone Scams, 6/16/2011 1:53:00 PM -07:00
        Combating social engineering tactics, like cookiejacking, to stay safer online, 5/28/2011 12:02:26 PM -07:00
        Windows 7 is now Common Criteria Certified!, 4/27/2011 9:35:01 AM -07:00
    
    Windows Home Server Blog
        Connecting Windows 8 Consumer Preview with Windows Home Server, 3/25/2012 9:06:00 AM -07:00
        Viridian PC Systems announces two new server models are available to order, 10/3/2011 12:36:00 PM -07:00
        PC Specialist to release Windows Home Server 2011, 9/27/2011 10:27:37 AM -07:00
    
    Springboard Series Blog
        Windows 8 Is Ready For Your Enterprise, 8/16/2012 9:59:00 AM -07:00
        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
    

    如果您選擇 [移除] 按鈕,在應用程式完成下載內容之前,結果會類似下列的輸出。

    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
        Windows Restart and Recovery Recipe, 3/21/2011 2:13:24 PM -07:00
    
    Extreme Windows Blog
        Samsung Series 9 27” PLS Display: Amazing Picture, 8/20/2012 2:41:48 PM -07:00
        NVIDIA GeForce GTX 660 Ti Graphics Card: Affordable Graphics Powerhouse, 8/16/2012 10:56:19 AM -07:00
        HP Z820 Workstation: Rising To the Challenge, 8/14/2012 1:57:01 PM -07:00
    
    Blogging Windows
        Windows Upgrade Offer Registration Now Available, 8/20/2012 1:01:00 PM -07:00
        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
    
    Windows for your Business
        What Windows 8 RTM Means for Businesses, 8/1/2012 9:01:00 AM -07:00
        Higher-Ed Learning with Windows 8, 7/26/2012 12:03:00 AM -07:00
        Second Public Beta of App-V 5.0 Now Available with Office Integration, 7/24/2012 10:07:26 AM -07:00
    
    Downloads canceled by the Cancel button.
    Cancellation exception bubbles up to the caller.
    

設定範例

您可以下載應用程式,建置自己或檢閱程式碼在這個主題的結尾,而不需要實作它。在您的電腦上安裝 Visual Studio 2012 和 Windows 8 上執行此應用程式。

下載完成的應用程式

  1. 下載壓縮檔) Async 範例:在 .NET 和 Windows 執行階段之間的橋接 AsTask & (取消)

  2. 解壓縮您下載的檔案,然後啟動 Visual Studio。

  3. 在功能表列上,選擇 [檔案]、[開啟]、[專案/方案]。

  4. 巡覽至保存解壓縮的範例程式碼的資料夾,然後開啟方案 (.sln) 檔。

  5. 選擇 F5 鍵建置及執行專案。

    執行程式碼幾次驗證可以移除在不同的點。

建置完成的應用程式

  1. 啟動 Visual Studio。

  2. 在功能表列上,選擇 [檔案]、[新增]、[專案]。

    [新增專案] 對話方塊隨即開啟。

  3. 在 [安裝] 中, [ [範本] 分類中,選取 [Visual Basic] 或 [Visual C#]],然後選取 [Windows 市集]。

  4. 從專案類型清單中,選取 [空白的應用程式 (XAML)]。

  5. 將專案命名為 BlogFeedWithCancellation,然後選擇 [OK] 按鈕。

    新專案即會出現於 [方案總管] 中。

  6. 在 [方案總管] 中,開啟 MainPage.xaml 的捷徑功能表,然後選擇 [開啟]。

  7. 在 [XAML] 視窗中 MainPage.xaml,以下列程式碼取代程式碼。

    <Page
        x:Class="BlogFeedWithCancellation.MainPage"
        xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="using:BlogFeedWithCancellation"
        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="Left" Margin="325,77,0,0" VerticalAlignment="Top" Click="StartButton_Click" Height="145" Background="#FFA89B9B" FontSize="36" Width="355"  />
            <Button x:Name="CancelButton" Content="Cancel" HorizontalAlignment="Left" Margin="684,77,0,0" VerticalAlignment="Top" Height="145" Background="#FFA89B9B" Click="CancelButton_Click" FontSize="36" Width="355"  />
            <TextBox x:Name="ResultsTextBox" HorizontalAlignment="Left" Margin="325,222,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Height="546" FontSize="10" ScrollViewer.VerticalScrollBarVisibility="Visible" Width="711" />
        </Grid>
    </Page>
    

    包含文字方塊的簡單視窗,開始按鈕和取消按鈕隨即出現在 [設計] 視窗中 MainPage.xaml。

  8. 在 [方案總管] 中,開啟或 MainPage.xaml.vb MainPage.xaml.cs 的捷徑功能表,然後選擇 [檢視程式碼]。

  9. 使用下列程式碼取代或 MainPage.xaml.vb MainPage.xaml.cs 的程式碼。

    ' Add an Imports statement for SyndicationClient.
    Imports Windows.Web.Syndication
    ' Add an Imports statement for Tasks.
    Imports System.Threading.Tasks
    ' Add an Imports statement for CancellationToken.
    Imports System.Threading
    
    
    Public NotInheritable Class MainPage
        Inherits Page
    
        ' ***Declare a System.Threading.CancellationTokenSource.
        Dim cts As CancellationTokenSource
    
        Private Async Sub StartButton_Click(sender As Object, e As RoutedEventArgs)
            ResultsTextBox.Text = ""
            ' Prevent unexpected reentrance.
            StartButton.IsEnabled = False
    
            ' ***Instantiate the CancellationTokenSource.
            cts = New CancellationTokenSource()
    
            Try
                ' ***Send a token to carry the message if cancellation is requested.
                Await DownloadBlogsAsync(cts.Token)
    
                ' ***Check for cancellations.
            Catch op As OperationCanceledException
                ' In practice, this catch block often is empty. It is used to absorb
                ' the exception,
                ResultsTextBox.Text &= vbCrLf & "Cancellation exception bubbles up to the caller."
    
                ' Check for other exceptions.
            Catch ex As Exception
                ResultsTextBox.Text =
                    "Page could not be loaded." & vbCrLf & "Exception: " & ex.ToString()
            End Try
    
            ' ***Set the CancellationTokenSource to null when the work is complete.
            cts = Nothing
    
            ' In case you want to try again.
            StartButton.IsEnabled = True
        End Sub
    
    
        ' Provide a parameter for the CancellationToken.
        Async Function DownloadBlogsAsync(ct As CancellationToken) As Task
            Dim client As Windows.Web.Syndication.SyndicationClient = New SyndicationClient()
    
            Dim uriList = CreateUriList()
    
            ' Force the SyndicationClient to download the information.
            client.BypassCacheOnRetrieve = True
    
    
            ' The following code avoids the use of implicit typing (var) so that you 
            ' can identify the types clearly.
    
            For Each uri In uriList
                ' ***These three lines are combined in the single statement that follows them.
                'Dim feedOp As IAsyncOperationWithProgress(Of SyndicationFeed, RetrievalProgress) =
                '    client.RetrieveFeedAsync(uri)
                'Dim feedTask As Task(Of SyndicationFeed) = feedOp.AsTask(ct)
                'Dim feed As SyndicationFeed = Await feedTask
    
                ' ***You can combine the previous three steps in one expression.
                Dim feed As SyndicationFeed = Await client.RetrieveFeedAsync(uri).AsTask(ct)
    
                DisplayResults(feed, ct)
            Next
        End Function
    
    
        ' ***Add an event handler for the Cancel button.
        Private Sub cancelButton_Click(sender As Object, e As RoutedEventArgs)
            If cts IsNot Nothing Then
                cts.Cancel()
                ResultsTextBox.Text &= vbCrLf & "Downloads canceled by the Cancel button."
            End If
        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/business/atom.aspx"),
                        New Uri("https://windowsteamblog.com/windows/b/windowsexperience/atom.aspx"),
                        New Uri("https://windowsteamblog.com/windows/b/windowssecurity/atom.aspx"),
                        New Uri("https://windowsteamblog.com/windows/b/windowshomeserver/atom.aspx"),
                        New Uri("https://windowsteamblog.com/windows/b/springboard/atom.aspx")
                    }
            Return uriList
        End Function
    
    
        ' You can pass the CancellationToken to this method if you think you might use a
        ' cancellable API here in the future.
        Sub DisplayResults(sf As SyndicationFeed, ct As CancellationToken)
            ' Title of the blog.
            ResultsTextBox.Text &= sf.Title.Text & vbCrLf
    
            ' Titles and dates for the first three blog posts.
            For i As Integer = 0 To If(sf.Items.Count >= 3, 2, sf.Items.Count)
                ResultsTextBox.Text &= vbTab & sf.Items.ElementAt(i).Title.Text & ", " &
                        sf.Items.ElementAt(i).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 Tasks.
    using System.Threading.Tasks;
    // Add a using directive for CancellationToken.
    using System.Threading;
    
    
    namespace BlogFeedWithCancellation
    {
        public sealed partial class MainPage : Page
        {
            // ***Declare a System.Threading.CancellationTokenSource.
            CancellationTokenSource cts;
    
            public MainPage()
            {
                this.InitializeComponent();
            }
    
    
            private async void StartButton_Click(object sender, RoutedEventArgs e)
            {
                ResultsTextBox.Text = "";
                // Prevent unexpected reentrance.
                StartButton.IsEnabled = false;
    
                // ***Instantiate the CancellationTokenSource.
                cts = new CancellationTokenSource();
    
                try
                {
                    // ***Send a token to carry the message if cancellation is requested.
                    await DownloadBlogsAsync(cts.Token);
                }
                // ***Check for cancellations.
                catch (OperationCanceledException)
                {
                    // In practice, this catch block often is empty. It is used to absorb
                    // the exception,
                    ResultsTextBox.Text += "\r\nCancellation exception bubbles up to the caller.";
                }
                // Check for other exceptions.
                catch (Exception ex)
                {
                    ResultsTextBox.Text =
                        "Page could not be loaded.\r\n" + "Exception: " + ex.ToString();
                }
    
                // ***Set the CancellationTokenSource to null when the work is complete.
                cts = null;
    
                // In case you want to try again.
                StartButton.IsEnabled = true;
            }
    
    
            // ***Provide a parameter for the CancellationToken.
            async Task DownloadBlogsAsync(CancellationToken ct)
            {
                Windows.Web.Syndication.SyndicationClient client = new SyndicationClient();
    
                var uriList = CreateUriList();
    
                // Force the SyndicationClient to download the information.
                client.BypassCacheOnRetrieve = true;
    
                // The following code avoids the use of implicit typing (var) so that you 
                // can identify the types clearly.
    
                foreach (var uri in uriList)
                {
                    // ***These three lines are combined in the single statement that follows them.
                    //IAsyncOperationWithProgress<SyndicationFeed, RetrievalProgress> feedOp = 
                    //    client.RetrieveFeedAsync(uri);
                    //Task<SyndicationFeed> feedTask = feedOp.AsTask(ct);
                    //SyndicationFeed feed = await feedTask;
    
                    // ***You can combine the previous three steps in one expression.
                    SyndicationFeed feed = await client.RetrieveFeedAsync(uri).AsTask(ct);
    
                    DisplayResults(feed);
                }
            }
    
    
    
            // ***Add an event handler for the Cancel button.
            private void CancelButton_Click(object sender, RoutedEventArgs e)
            {
                if (cts != null)
                {
                    cts.Cancel();
                    ResultsTextBox.Text += "\r\nDownloads canceled by the Cancel button.";
                }
            }
    
    
            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/business/atom.aspx"),
                    new Uri("https://windowsteamblog.com/windows/b/windowsexperience/atom.aspx"),
                    new Uri("https://windowsteamblog.com/windows/b/windowssecurity/atom.aspx"),
                    new Uri("https://windowsteamblog.com/windows/b/windowshomeserver/atom.aspx"),
                    new Uri("https://windowsteamblog.com/windows/b/springboard/atom.aspx")
                };
                return uriList;
            }
    
    
            // You can pass the CancellationToken to this method if you think you might use a
            // cancellable API here in the future.
            void DisplayResults(SyndicationFeed sf)
            {
                // Title of the blog.
                ResultsTextBox.Text += sf.Title.Text + "\r\n";
    
                // Titles and dates for the first three blog posts.
                for (int i = 0; i < (sf.Items.Count < 3 ? sf.Items.Count : 3); i++)    // Is Math.Min better?
                {
                    ResultsTextBox.Text += "\t" + sf.Items.ElementAt(i).Title.Text + ", " +
                        sf.Items.ElementAt(i).PublishedDate.ToString() + "\r\n";
                }
    
                ResultsTextBox.Text += "\r\n";
            }
        }
    }
    
  10. 選取 F5 鍵執行程式,然後選取 [開始] 按鈕。

請參閱

概念

WhenAny:銜接 .NET Framework 和 Windows 執行階段 (C# 和 Visual Basic)

取消一項或多項工作 (C# 和 Visual Basic)

在一段時間後取消工作 (C# 和 Visual Basic)

當其中一項工作完成時,取消剩餘的工作 (C# 和 Visual Basic)

取消語彙基元