博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
第二十章:异步和文件I/O.(十九)
阅读量:6943 次
发布时间:2019-06-27

本文共 5168 字,大约阅读时间需要 17 分钟。

取消作业

到目前为止显示的两个Mandelbrot程序仅用于生成单个图像,因此一旦启动它就不可能取消该作业。但是,在一般情况下,您需要为用户提供一种便利,以摆脱冗长的后台作业。
尽管您可以将自己的一个取消系统放在一起,但System.Threading命名空间已经为您提供了一个名为CancellationTokenSource的类和一个名为CancellationToken的结构。
以下是它的工作原理:
程序创建一个CancellationTokenSource以用于特定的异步方法。 CancellationTokenSource类定义名为Token的属性,该属性返回CancellationToken。此CancellationToken值将传递给异步方法。异步方法定期调用CancellationToken的IsCancellationRequested方法。此方法通常返回false。
当程序想要取消异步操作时(可能是响应某些用户输入),它调用CancellationTokenSource的Cancel方法。下次异步方法调用CancellationToken的IsCancellationRequested方法时,该方法返回true,因为已请求取消。异步方法可以选择如何
停止运行,也许是一个简单的return语句。
然而,通常采用不同的方法。异步方法可以简单地调用ThrowIfCancellationRequested方法,而不是调用CancellationToken的IsCancellationRequested方法。如果已请求取消,则异步方法将通过引发OperationCanceledException停止执行。
这意味着await运算符必须是try块的一部分,但正如您所见,这通常是处理文件时的情况,因此它不会添加太多额外的代码,并且程序可以简单地处理取消另一种形式的例外。
MandelbrotCancellation程序演示了这种技术。 XAML文件现在有第二个按钮,标记为“取消”,最初被禁用:

代码隐藏文件现在有一个更广泛的OnCalculateButtonClicked方法。 首先禁用“计算”按钮并启用“取消”按钮。 它创建一个新的Cancellation TokenSource对象,并将Token属性传递给CalculateMandelbrotAsync。 OnCancelButtonClicked方法负责在CancellationTokenSource对象上调用Cancel。 CalculateMandelbrotAsync方法以与报告进度相同的速率调用ThrowIfCancellationRequested方法。 OnCalculateButtonClicked方法捕获异常,该方法通过重新启用“计算”按钮进行另一次尝试来响应:

public partial class MandelbrotCancellationPage : ContentPage{    static readonly Complex center = new Complex(-0.75, 0);    static readonly Size size = new Size(2.5, 2.5);    const int pixelWidth = 1000;    const int pixelHeight = 1000;    const int iterations = 100;    Progress
progressReporter; CancellationTokenSource cancelTokenSource; public MandelbrotCancellationPage() { InitializeComponent(); progressReporter = new Progress
((double value) => { progressBar.Progress = value; }); } async void OnCalculateButtonClicked(object sender, EventArgs args) { // Configure the UI for a background process. calculateButton.IsEnabled = false; cancelButton.IsEnabled = true; cancelTokenSource = new CancellationTokenSource(); try { // Render the Mandelbrot set on a bitmap. BmpMaker bmpMaker = await CalculateMandelbrotAsync(progressReporter, cancelTokenSource.Token); image.Source = bmpMaker.Generate(); } catch (OperationCanceledException) { calculateButton.IsEnabled = true; progressBar.Progress = 0; } catch (Exception) { // Shouldn't occur in this case. } cancelButton.IsEnabled = false; } void OnCancelButtonClicked(object sender, EventArgs args) { cancelTokenSource.Cancel(); } Task
CalculateMandelbrotAsync(IProgress
progress, CancellationToken cancelToken) { return Task.Run
(() => { BmpMaker bmpMaker = new BmpMaker(pixelWidth, pixelHeight); for (int row = 0; row < pixelHeight; row++) { double y = center.Imaginary - size.Height / 2 + row * size.Height / pixelHeight; // Report the progress. progress.Report((double)row / pixelHeight); // Possibly cancel. cancelToken.ThrowIfCancellationRequested(); for (int col = 0; col < pixelWidth; col++) { double x = center.Real - size.Width / 2 + col * size.Width / pixelWidth; Complex c = new Complex(x, y); Complex z = 0; int iteration = 0; bool isMandelbrotSet = false; if ((c - new Complex(-1, 0)).MagnitudeSquared < 1.0 / 16) { isMandelbrotSet = true; } // http://www.reenigne.org/blog/algorithm-for-mandelbrot-cardioid/ else if (c.MagnitudeSquared * (8 * c.MagnitudeSquared - 3) < 3.0 / 32 - c.Real) { isMandelbrotSet = true; } else { do { z = z * z + c; iteration++; } while (iteration < iterations && z.MagnitudeSquared < 4); isMandelbrotSet = iteration == iterations; } bmpMaker.SetPixel(row, col, isMandelbrotSet ? Color.Black : Color.White); } } return bmpMaker; }, cancelToken); }}

CancellationToken也作为第二个参数传递给Task.Run。 这不是必需的,但它允许Task.Run方法在已经请求取消甚至开始之前跳过大量工作。

另请注意,该代码现在跳过大型心形指针。 注释引用一个网页,该网页会在您想要检查数学的情况下派生公式。

转载地址:http://zzonl.baihongyu.com/

你可能感兴趣的文章
手把手教你反编译别人的APP
查看>>
MapReduce的集群行为和框架
查看>>
Oracle表变化趋势追踪记录
查看>>
排序算法总结之希尔排序
查看>>
python中set使用
查看>>
gradle项目与maven项目相互转化(转)
查看>>
MAC下安装与配置MySQL
查看>>
linux系统的crond服务
查看>>
Restore Volume 操作 - 每天5分钟玩转 OpenStack(60)
查看>>
sqool导出oracle数据
查看>>
MyBatis动态传入表名,字段名参数的解决办法
查看>>
Windows平台下安装Hadoop
查看>>
oracle11gR2静默安装
查看>>
理解javascript中的浏览器窗口——窗口基本操作
查看>>
Directx11学习笔记【二十】 使用DirectX Tool Kit加载mesh
查看>>
【Linux】NAT模式下关于主机ping不通虚拟机的问题
查看>>
SpringMVC 参数注入
查看>>
mysql去重, 把url重复且区为空的中去掉、统计重复数据、、结果集去重合并成一行...
查看>>
atitit.attilax的软件 架构 理念.docx
查看>>
EF实体框架之CodeFirst四
查看>>