Отмена. Связывание .NET Framework и среды выполнения Windows (C# и Visual Basic)
Можно развернуть ресурсы путем объединения возможности платформы .NET Framework и Среда выполнения Windows.Пример в этом разделе демонстрируется использование экземпляр .NET FrameworkCancellationToken, чтобы добавить кнопку отмены в приложение, использующее метод Среда выполнения Windows, чтобы загрузить веб-канал блога из Интернета.
Примечание |
---|
Запуск образца необходимо иметь Windows 8, на компьютере.Кроме того, если требуется запустить пример из Visual Studio, следует установить Visual Studio 2012 или Visual Studio Express 2012 для Windows 8 задать. |
AsTask предоставляет мост
Токен отмены для экземпляров Task, но метод Среда выполнения Windows создает IAsyncOperationWithProgress экземпляры.Можно использовать метод расширений AsTask в платформе .NET Framework к мосту между ними.
Метод 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>.В частности, код придает перегруженный метод AsTask, принимающую аргумент CancellationToken.
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, загрузил веб-канал блога, код отправляет свойство CancellationTokenSource.Tokencts в качестве аргумента.Свойство Token передает сообщение, если запрошена отмена.
Await DownloadBlogsAsync(cts.Token)
await DownloadBlogsAsync(cts.Token);
Вызов DownloadBlogsAsync расквартирован в инструкцию try-catch, которая содержит блок catch для OperationCanceledException, результаты при нажатии кнопки Отмена.Вызывающая сторона метода токена указывает, какое действие, выполняемое.В этом примере просто отображает сообщение.
Следующий код отображает полную оператора 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, RetrieveFeedAsync, Среда выполнения Windows и .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 следует установить на компьютере, чтобы запустить приложение.
Загрузить завершенное приложение
Загрузите сжатый файл из Пример Async. Использование моста между .NET и среда выполнения Windows (AsTask & отмену).
Распакуйте файл, который загружен, затем запустите Visual Studio.
В строке меню выберите Файл, Открыть, Проект/Решение.
Перейдите в папку, которая содержит распакованный пример кода, а затем откройте файл решения (SLN).
Выберите ключ F5 для построения и выполнения проекта.
Запустите его несколько раз проверить, можно отменить на разных этапах.
Построение завершенное приложение
Запустите Visual Studio.
В строке меню выберите Файл, Создать, Проект.
Откроется диалоговое окно Новый проект.
В Установлено в категории Шаблоны выберите Visual Basic или Visual C#, а затем пункт Магазин Windows.
В списке типов проекта выберите Пустое приложение (XAML).
Назовите проект BlogFeedWithCancellation, а затем нажмите кнопку ОК.
В обозревателе решений появится новый проект.
В Обозреватель решений откройте контекстное меню для MainPage.xaml, а затем выберите Открыть.
В окне 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.
В Обозреватель решений откройте контекстное меню для 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 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"; } } }
Нажмите клавишу F5, чтобы запустить программу, а затем нажмите кнопку Start.
См. также
Основные понятия
WhenAny. Связывание .NET Framework и среды выполнения Windows (C# и Visual Basic)
Отменить задачу или список задач (C# и Visual Basic)
Отменить задачи после определенного периода времени (C# и Visual Basic)
Отменить оставшиеся задачи после завершения одной из них (C# и Visual Basic)