异步编程一些示例

一些示例

项目将创建一个 UI,其中包含用于启动进程和取消进程的按钮,如下图所示。 这些按钮名为 startButtoncancelButton
这里写图片描述

取消一个异步任务或一组任务 (C#)

如果不想等待异步应用程序完成,可以设置一个按钮用来取消它。 通过遵循本主题中的示例,可以为下载一个或一组网站内容的应用程序添加一个取消按钮。

取消一个任务

下列代码是取消单个任务示例的完整 MainWindow.xaml.cs 文件。

using System;  
using System.Collections.Generic;  
using System.Linq;  
using System.Text;  
using System.Threading.Tasks;  
using System.Windows;  
using System.Windows.Controls;  
using System.Windows.Data;  
using System.Windows.Documents;  
using System.Windows.Input;  
using System.Windows.Media;  
using System.Windows.Media.Imaging;  
using System.Windows.Navigation;  
using System.Windows.Shapes;  
using System.Net.Http;    
using System.Threading;
  
namespace CancelATask  
{  
    public partial class MainWindow : Window  
    {  
        //声明一个System.Threading.CancellationTokenSource.  
        CancellationTokenSource cts;  
  
        public MainWindow()  
        {  
            InitializeComponent();  
        }  
  
        private async void startButton_Click(object sender, RoutedEventArgs e)  
        {  
            //实例化CancellationTokenSource.  
            cts = new CancellationTokenSource();  
  
            resultsTextBox.Clear();  
  
            try  
            {   
                //如果请求取消,则发送令牌以携带消息。
                int contentLength = await AccessTheWebAsync(cts.Token);  
                resultsTextBox.Text +=  
                    String.Format("\r\nLength of the downloaded string: {0}.\r\n", contentLength);  
            }   
            catch (OperationCanceledException)  
            {  
               //如果请求取消,则返回OperationCanceledException
                resultsTextBox.Text += "\r\nDownload canceled.\r\n";  
            }  
            catch (Exception)  
            {  
                resultsTextBox.Text += "\r\nDownload failed.\r\n";  
            }  
  
            //下载完成后,将CancellationTokenSource设置为空
            cts = null;   
        }  
   
        //为Cancel 按钮添加一个事件处理程序。
        private void cancelButton_Click(object sender, RoutedEventArgs e)  
        {  
            if (cts != null)  
            {  
                cts.Cancel();  
            }  
        }  
   
        //提供一个CancellationToken参数
        async Task<int> AccessTheWebAsync(CancellationToken ct)  
        {  
            HttpClient client = new HttpClient();  
  
            resultsTextBox.Text += String.Format("\r\nReady to download.\r\n");  
  
            //您可能需要放慢速度才能有机会取消。
            await Task.Delay(2500);  
   
            //GetAsync返回一个Task<HttpResponseMessage> 
            //如果选择Cancel按钮,则ct参数将携带消息。
            HttpResponseMessage response = await client.GetAsync("http://www.twitter.com/dd470362.aspx", ct);  
  
           
            //从HttpResponseMessage中检索网站内容
            byte[] urlContents = await response.Content.ReadAsByteArrayAsync();  
  
            //该方法的结果是下载网站页面的字符长度
            return urlContents.Length;  
        }  
    }  
  
    // 成功下载的输出:
  
    // Ready to download.  
  
    // Length of the downloaded string: 158125.  
  
  
    // 或者,如果取消:  
  
    // Ready to download.  
  
    // Download canceled.  
}  

取消任务列表

下列代码是取消任务列表示例的完整 MainWindow.xaml.cs 文件。

using System;  
using System.Collections.Generic;  
using System.Linq;  
using System.Text;  
using System.Threading.Tasks;  
using System.Windows;  
using System.Windows.Controls;  
using System.Windows.Data;  
using System.Windows.Documents;  
using System.Windows.Input;  
using System.Windows.Media;  
using System.Windows.Media.Imaging;  
using System.Windows.Navigation;  
using System.Windows.Shapes;  
   
using System.Net.Http;    
using System.Threading;  
  
namespace CancelAListOfTasks  
{  
    public partial class MainWindow : Window  
    {  
        //声明一个System.Threading.CancellationTokenSource.
        CancellationTokenSource cts;  
  
        public MainWindow()  
        {  
            InitializeComponent();  
        }  
  
        private async void startButton_Click(object sender, RoutedEventArgs e)  
        {  
           
            cts = new CancellationTokenSource();  
  
            resultsTextBox.Clear();  
  
            try  
            {  
                await AccessTheWebAsync(cts.Token);  
                
                resultsTextBox.Text += "\r\nDownloads complete.";  
            }  
            catch (OperationCanceledException)  
            {  
                resultsTextBox.Text += "\r\nDownloads canceled.";  
            }  
            catch (Exception)  
            {  
                resultsTextBox.Text += "\r\nDownloads failed.";  
            }  
  
            cts = null;  
        }  
  
        //为Cancel 按钮添加一个事件处理程序。
        private void cancelButton_Click(object sender, RoutedEventArgs e)  
        {  
            if (cts != null)  
            {  
                cts.Cancel();  
            }  
        }  
  
      
        //将返回类型更改为Task,因为该方法没有返回语句。 
        async Task AccessTheWebAsync(CancellationToken ct)  
        {   
            HttpClient client = new HttpClient();  
  
            //调用SetUpURLList来创建一个Web地址列表
            List<string> urlList = SetUpURLList();  
   
            //添加一个循环来处理网址列表
            foreach (var url in urlList)  
            {   
                //GetAsync返回一个Task<HttpResponseMessage> 
                //如果选择Cancel按钮,则ct参数将携带消息。 
                
                //请注意,取消按钮可以取消所有剩余的下载
                HttpResponseMessage response = await client.GetAsync(url, ct);  
  
                //从HttpResponseMessage中检索网站内容
                byte[] urlContents = await response.Content.ReadAsByteArrayAsync();  
  
                resultsTextBox.Text +=  
                    String.Format("\r\nLength of the downloaded string: {0}.\r\n", urlContents.Length);  
            }  
        }  
  
        private List<string> SetUpURLList()  
        {  
            List<string> urls = new List<string>   
            {   
                "http://www.twitter.com",  
                "http://www.twitter.com/hh290138.aspx",  
                "http://www.twitter.com/hh290140.aspx",  
                "http://www.twitter.com/dd470362.aspx",  
                "http://www.twitter.com/aa578028.aspx",  
                "http://www.twitter.com/ms404677.aspx",  
                "http://www.twitter.com/ff730837.aspx"  
            };  
            return urls;  
        }  
    }  
  
    //如果您不选择取消,则输出:
  
    //Length of the downloaded string: 35939.  
  
    //Length of the downloaded string: 237682.  
  
    //Length of the downloaded string: 128607.  
  
    //Length of the downloaded string: 158124.  
  
    //Length of the downloaded string: 204890.  
  
    //Length of the downloaded string: 175488.  
  
    //Length of the downloaded string: 145790.  
  
    //Downloads complete.  
  
    //如果您选择取消: 
  
    //Length of the downloaded string: 35939.  
  
    //Length of the downloaded string: 237682.  
  
    //Length of the downloaded string: 128607.  
  
    //Downloads canceled.  
}  

在一段时间后取消异步任务 (C#)

如果不希望等待操作结束,可使用 CancellationTokenSource.CancelAfter 方法在一段时间后取消异步操作。 此方法会计划取消未在 CancelAfter 表达式指定的时间段内完成的任何关联任务。

完整的示例

请注意,必须为 System.Net.Http 添加引用。

using System;  
using System.Collections.Generic;  
using System.Linq;  
using System.Text;  
using System.Threading.Tasks;  
using System.Windows;  
using System.Windows.Controls;  
using System.Windows.Data;  
using System.Windows.Documents;  
using System.Windows.Input;  
using System.Windows.Media;  
using System.Windows.Media.Imaging;  
using System.Windows.Navigation;  
using System.Windows.Shapes;
using System.Net.Http;  
using System.Threading;  
  
namespace CancelAfterTime  
{  
    public partial class MainWindow : Window  
    {  
        CancellationTokenSource cts;  
  
        public MainWindow()  
        {  
            InitializeComponent();  
        }  
  
        private async void startButton_Click(object sender, RoutedEventArgs e)  
        {   
            cts = new CancellationTokenSource();  
  
            resultsTextBox.Clear();  
  
            try  
            {  
                //设置CancellationTokenSource以在2.5秒后取消。 (您可以调整时间。)
                cts.CancelAfter(2500);  
  
                await AccessTheWebAsync(cts.Token);  
                resultsTextBox.Text += "\r\nDownloads succeeded.\r\n";  
            }  
            catch (OperationCanceledException)  
            {  
                resultsTextBox.Text += "\r\nDownloads canceled.\r\n";  
            }  
            catch (Exception)  
            {  
                resultsTextBox.Text += "\r\nDownloads failed.\r\n";  
            }  
  
            cts = null;   
        }  
   
        //您仍然可以使用取消按钮。
        private void cancelButton_Click(object sender, RoutedEventArgs e)  
        {  
            if (cts != null)  
            {  
                cts.Cancel();  
            }  
        }  
  
        async Task AccessTheWebAsync(CancellationToken ct)  
        {  
            HttpClient client = new HttpClient();   
            List<string> urlList = SetUpURLList();  
  
            foreach (var url in urlList)  
            {  
                //取消按钮取消所有剩余的下载。
                HttpResponseMessage response = await client.GetAsync(url, ct);  
  
                //从HttpResponseMessage中检索网站内容
                byte[] urlContents = await response.Content.ReadAsByteArrayAsync();  
  
                resultsTextBox.Text +=  
                    String.Format("\r\nLength of the downloaded string: {0}.\r\n", urlContents.Length);  
            }  
        }  
  
        private List<string> SetUpURLList()  
        {  
            List<string> urls = new List<string>   
            {   
                "http://www.twitter.com",  
                "http://www.twitter.com/ee256749.aspx",  
                ...
            };  
            return urls;  
        }  
    }  
  
    //示例输出:
  
    // Length of the downloaded string: 35990.  
  
    // Length of the downloaded string: 407399.  
  
    // Length of the downloaded string: 226091.  
  
    // Downloads canceled.  
}  

在完成一个异步任务后取消剩余任务 (C#)

通过结合使用 Task.WhenAny 方法和 CancellationToken,可在一个任务完成时取消所有剩余任务。WhenAny 方法采用任务集合中的一个参数。该方法启动所有任务,并返回单个任务。 当集合中任意任务完成时,完成单个任务。

此示例演示如何结合使用取消标记与 WhenAny 保留任务集合中第一个要完成的任务,并取消剩余任务。 每个任务都下载网站内容。

本示例显示第一个完成的下载的内容长度,并取消其他下载。

完整的示例

using System;  
using System.Collections.Generic;  
using System.Linq;  
using System.Text;  
using System.Threading.Tasks;  
using System.Windows;  
using System.Windows.Controls;  
using System.Windows.Data;  
using System.Windows.Documents;  
using System.Windows.Input;  
using System.Windows.Media;  
using System.Windows.Media.Imaging;  
using System.Windows.Navigation;  
using System.Windows.Shapes;
using System.Net.Http;  
using System.Threading;  
  
namespace CancelAfterOneTask  
{  
    public partial class MainWindow : Window  
    {  
        CancellationTokenSource cts;  
  
        public MainWindow()  
        {  
            InitializeComponent();  
        }  
  
        private async void startButton_Click(object sender, RoutedEventArgs e)  
        {  
            cts = new CancellationTokenSource();  
  
            resultsTextBox.Clear();  
  
            try  
            {  
                await AccessTheWebAsync(cts.Token);  
                resultsTextBox.Text += "\r\nDownload complete.";  
            }  
            catch (OperationCanceledException)  
            {  
                resultsTextBox.Text += "\r\nDownload canceled.";  
            }  
            catch (Exception)  
            {  
                resultsTextBox.Text += "\r\nDownload failed.";  
            }  
            cts = null;  
        }  
        
        private void cancelButton_Click(object sender, RoutedEventArgs e)  
        {  
            if (cts != null)  
            {  
                cts.Cancel();  
            }  
        }  
        
        async Task AccessTheWebAsync(CancellationToken ct)  
        {  
            HttpClient client = new HttpClient();  
  
            List<string> urlList = SetUpURLList();  
             
            //创建一个查询,该查询在执行时返回一组任务。
            IEnumerable<Task<int>> downloadTasksQuery =  
                from url in urlList select ProcessURLAsync(url, client, ct);  
  
            //使用ToArray执行查询并开始下载任务
            Task<int>[] downloadTasks = downloadTasksQuery.ToArray();  
  
            //调用WhenAny然后等待结果。首先完成的任务分配给firstFinishedTask。 
            Task<int> firstFinishedTask = await Task.WhenAny(downloadTasks);  
  
            //取消下载的其余部分,你只是想要第一个。 
            cts.Cancel();  
  
            //等待第一个完成的任务并显示结果。
            var length = await firstFinishedTask;  
            resultsTextBox.Text += String.Format("\r\nLength of the downloaded website:  {0}\r\n", length);  
        }  
   
        //将网站的处理步骤集中到一个异步方法中。 
        async Task<int> ProcessURLAsync(string url, HttpClient client, CancellationToken ct)  
        {  
            //GetAsync返回一个Task<HttpResponseMessage>
            HttpResponseMessage response = await client.GetAsync(url, ct);  
  
            //从HttpResponseMessage中检索网站内容
            byte[] urlContents = await response.Content.ReadAsByteArrayAsync();  
  
            return urlContents.Length;  
        }  
        
        private List<string> SetUpURLList()  
        {  
            List<string> urls = new List<string>   
            {   
                "http://www.twitter.com",  
                "http://www.twitter.com/hh290138.aspx",  
                "http://www.twitter.com/hh290140.aspx",  
                ...
            };  
            return urls;  
        }  
    }  
    //示例输出:
  
    // Length of the downloaded website:  158856  
  
    // Download complete.  
}  

启动多个异步任务并在其完成时进行处理 (C#)

通过使用 Task.WhenAny,可以同时启动多个任务,并在它们完成时逐个对它们进行处理,而不是按照它们的启动顺序进行处理。

下面的示例使用查询来创建一组任务。 每个任务都下载指定网站的内容。 在对 while 循环的每次迭代中,对 WhenAny 的等待调用返回任务集合中首先完成下载的任务。 此任务从集合中删除并进行处理。 循环重复进行,直到集合中不包含任何任务。

完整的示例

请注意,必须为 System.Net.Http 添加引用。

using System;  
using System.Collections.Generic;  
using System.Linq;  
using System.Text;  
using System.Threading.Tasks;  
using System.Windows;  
using System.Windows.Controls;  
using System.Windows.Data;  
using System.Windows.Documents;  
using System.Windows.Input;  
using System.Windows.Media;  
using System.Windows.Media.Imaging;  
using System.Windows.Navigation;  
using System.Windows.Shapes;  
  
using System.Net.Http;  
using System.Threading;  
  
namespace ProcessTasksAsTheyFinish  
{  
    public partial class MainWindow : Window  
    {  
        CancellationTokenSource cts;  
  
        public MainWindow()  
        {  
            InitializeComponent();  
        }  
  
        private async void startButton_Click(object sender, RoutedEventArgs e)  
        {  
            resultsTextBox.Clear();  
  
            //实例化CancellationTokenSource
            cts = new CancellationTokenSource();  
  
            try  
            {  
                await AccessTheWebAsync(cts.Token);  
                resultsTextBox.Text += "\r\nDownloads complete.";  
            }  
            catch (OperationCanceledException)  
            {  
                resultsTextBox.Text += "\r\nDownloads canceled.\r\n";  
            }  
            catch (Exception)  
            {  
                resultsTextBox.Text += "\r\nDownloads failed.\r\n";  
            }  
  
            cts = null;  
        }  
  
        private void cancelButton_Click(object sender, RoutedEventArgs e)  
        {  
            if (cts != null)  
            {  
                cts.Cancel();  
            }  
        }  
  
        async Task AccessTheWebAsync(CancellationToken ct)  
        {  
            HttpClient client = new HttpClient();  
            
            List<string> urlList = SetUpURLList();  
  
            //创建一个查询,该查询在执行时返回一组任务。
            IEnumerable<Task<int>> downloadTasksQuery =  
                from url in urlList select ProcessURL(url, client, ct);  
  
            //使用ToList执行查询并启动任务  
            List<Task<int>> downloadTasks = downloadTasksQuery.ToList();  
  
            //添加一个循环来一次处理一个任务,直到没有剩余任务。
            while (downloadTasks.Count > 0)  
            {  
                    //确定完成的第一项任务
                    Task<int> firstFinishedTask = await Task.WhenAny(downloadTasks);  
  
                    // ***从列表中删除选定的任务,以便不会多次处理它。
                    downloadTasks.Remove(firstFinishedTask);  
  
                    //await 完成的任务
                    int length = await firstFinishedTask;  
                    resultsTextBox.Text += String.Format("\r\nLength of the download:  {0}", length);  
            }  
        }  
  
        private List<string> SetUpURLList()  
        {  
            List<string> urls = new List<string>   
            {   
                "http://www.twitter.com",
                "http://www.twitter.com/ff730837.aspx" 
                ... 
            };  
            return urls;  
        }  
  
        async Task<int> ProcessURL(string url, HttpClient client, CancellationToken ct)  
        {  
            HttpResponseMessage response = await client.GetAsync(url, ct);  
            
            byte[] urlContents = await response.Content.ReadAsByteArrayAsync();  
  
            return urlContents.Length;  
        }  
    }  
}  
  
//示例输出:
  
// Length of the download:  226093  
// Length of the download:  412588  
// Length of the download:  175490  
// Length of the download:  204890  
// Length of the download:  158855  
// Length of the download:  145790  
// Length of the download:  44908  
// Downloads complete.  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值