以下示例代码段通过使用List<string> urls
编码技术读取/处理Web Url示例列表async/await
的内容来实现多任务处理功能(类似于MSDN演示示例:https://msdn.microsoft.com/en-us/library/jj155756.aspx) 。出于测试目的,Url List<string> urls
包含两个错误项目。
清单1. WPF中的错误处理async / await多个任务的实现
namespace ProcessTasksAsTheyFinish
{
public partial class MainWindow : Window
{
CancellationTokenSource cts;
// sample Url list containing erroneous items
private List<string> SetUpURLList()
{
List<string> urls = new List<string>
{
"http://msdn.microsoft.com",
"http://msdn.microsoft.com/library/windows/apps/br211380.aspx",
"error1",
"http://msdn.microsoft.com/en-us/library/aa578028.aspx",
"error2",
"http://msdn.microsoft.com/en-us/library/ms404677.aspx",
"http://msdn.microsoft.com/en-us/library/ff730837.aspx"
};
return urls;
}
public MainWindow() { InitializeComponent(); }
private async void startButton_Click(object sender, RoutedEventArgs e) {
resultsTextBox.Clear();
cts = new CancellationTokenSource();
try { await AccessTheWebAsync(cts.Token);}
finally { cts = null; }
}
private async Task AccessTheWebAsync(CancellationToken ct) {
try {
HttpClient client = new HttpClient();
// sample list of web addresses
List<string> urlList = SetUpURLList();
// query to create a collection of Tasks
IEnumerable<Task<int>> downloadTasksQuery =
from url in urlList select ProcessURL(url, client, ct);
// run multiple Tasks in async mode
await Task.WhenAll(downloadTasksQuery.ToList());
resultsTextBox.Text += "\r\nDownloads complete.";
}
catch (OperationCanceledException){
resultsTextBox.Text += "\r\nDownloads canceled.";
}
catch (Exception ex){
resultsTextBox.Text += Environment.NewLine + ex.Message;
}
}
private async Task<int> ProcessURL(string url, HttpClient client, CancellationToken ct)
{
try
{
HttpResponseMessage response = await client.GetAsync(url, ct);
byte[] urlContents = await response.Content.ReadAsByteArrayAsync();
resultsTextBox.Text += String.Format("\r\nLength: {0}", urlContents.Length);
return urlContents.Length;
}
catch
{
//if (cts != null) cts.Cancel();
throw;
}
}
}
}
// sample output:
// Length: 196315
// Length: 468941
// Length: 158496
// Length: 200790
// Length: 48022
// An invalid request URI was provided. The request URI must either be an absolute URI or BaseAddress must be set.
输出包含针对5个有效网址计算的长度信息以及与例外ex.Message
对应的错误通知。
目标是以这样的方式修改功能,即第一个异常将完全终止await Task.WhenAll
的多任务执行。换句话说,实现&#34;全部或者没有&#34;与等待多个Tasks
相关的业务逻辑。
在此示例中,通过使用Exception
将以下语句添加到CancellationToken
处理块(在清单1中显示为注释行)来实现:
if (cts != null) cts.Cancel();
输出文本按预期显示,对应于ex.Message
:
提供了无效的请求URI。请求URI必须是 必须设置绝对URI或BaseAddress。
已编辑:我一直在寻找相同的简化实现&#34;全部或全部&#34;功能(允许在第一个错误的Tasks
过程中终止整个Task.WhenAll
集)而不使用CancellationToken
。根据@Stephen Cleary发布的富有洞察力的评论,没有任何超载&#34;快捷方式&#34;选项并没有比当前更好的解决方案(简单性)。
答案 0 :(得分:2)
没有重载可以提供内置的这种功能。
通常,CancellationTokenSource
对象的自动取消不在BCL中(超时便捷方法除外,它根据计时器自动取消)。如果我冒险猜测,我会说BCL团队觉得这些超载的用例太多了,所以对于足够广泛的受众来说,它们不会有用。内置。
相反,适当的解决方案是在任何一个任务出现故障时自己触发CTS,这就是您的代码已经在做的事情。