标签:
用鼠标操作,我们习惯了延迟,过去几十年都是这样。有了触摸UI,应用程序要求立刻响应用户的请求。
C#5.0提供了更强大的异步编程,仅添加了两个新的关键字:async和await。
使用异步编程,方法调用是在后头运行(通常在线程和任务的帮助下),并且不会阻塞调用线程。
=》 所以 异步编程应该就是使用线程和任务进行编程。
另外,异步委托也是在线程和任务的帮助下完成的,它是基于事件的异步模式。
1.首先先了解一个概念:(WPF的,应该和WindowsForm差不多)
在WindowsForm和WPF程序中,拥有同步上下文的线程其实就是UI线程。意思就是WPF元素(窗口中显示的WPF对象)具有线程关联性,创建WPF元素的线程拥有所创建的元素,其它线程不能直接与这些WPF元素进行交互。
拥有线程关联性的WPF对象(应该就是窗口中显示的WPF对象,又叫WPF可视化对象)在类层次的某个位置继承自DispatherObject类。DispatherObject类提供了核实代码是否在正确的线程上执行、并且(如果没有在正确的线程上)是否能切换到正确的线程上的能力。
Dispatcher类(调度程序):它继承自DispatherObject基类,任何WPF可视化对象也继承自DispatherObject基类。
通过 对象.Dispather来访问管理该对象的调度程序。
成员:
Dispatcher:返回管理该对象的调度程序。
CheckAccess(): 如果代码在正确的线程上使用对象,就返回true,否则返回false。
VerifyAccess(): 如果代码在正确的线程上使用对象,就什么也不做,否则抛出InvalidOperationException异常。
1 //Dispather调度程序的使用 2 //在按钮的单击事件中创建线程来更新UI 3 private void Button_Click(object sender, RoutedEventArgs e) 4 { 5 Thread thread = new Thread(UpdataTextWrong); 6 thread.Start(); 7 } 8 9 private void UpdataTextWrong() 10 { 11 txt.Text = "Here is some new text."; // error 12 //TextBox对象通过调用VerityAccess()方法捕获这一非法操作。 13 14 this.Dispather.BeginInvoke(DispatherPriority.Normal, 15 (ThreadStart) delegate() { 16 txt.Text = "Here is some new text."; 17 }); //Ok 18 }
调度程序提供了Invoke()和BeginInvoke()方法。
Invoke方法将指定的代码封送到调度程序线程(UI),Invoke方法会阻塞线程,直到调度程序执行了你指定的代码。如果需要暂停异步操作,直到用户通过UI提供一些反馈,可以使用Invoke()。
BeginInvoke方法提供了Invoke方法的异步模式,不会阻塞线程。
2.再介绍下什么是异步编程?
三种不同模式的异步编程:异步模式、基于事件的异步模式、基于任务的异步模式(TAP)。
异步模式:
有些类提供了同步方法,也提供了同步方法的异步方法版本,如BeginXXX和EndXXX模式的方法。
HttpWebRequest类提供了这种模式,提供了BeginGetResponse()和EndGetResponse()。
委托类型定义了Invoke方法用于调用同步方法,并且定义了一个BeginInvoke方法和一个EndInvoke方法,用来采用异步模式调用方法。
基于事件的异步模式:
基于事件的异步模式定义了一个带有“Async”后缀的方法。
例如,对于同步方法DownloadString,WebClient类提供了一个异步变体方法DownloadAsync。
更具代表的类:BackgroundWorker类实现了基于事件的异步方法。并提供进度报告和取消支持。
BackgroundWorker成员:
RunWorkerAsync()方法: 开始执行。
DoWork事件: 需要执行的耗时任务。当BackgroundWorker对象调用RunWorkerAsync()方法后,从CLR线程池中提取一个自由线程,并在自由线程上触发DoWork事件。因此它不能访问共享数据(如窗口类中的字段)或用户界面。
RunWorkerCompletedEventArgs事件: DoWork事件结束后触发,运行在调度程序(UI线程)上。
WorkerReportsProgress属性: 要为进度添加支持,就必须设为true。
ReportProgress()方法: 报告进度。
ProgressChanged事件: 调用ReportProgress()方法报告进度时触发。可响应该事件,读取新的进度百分比并更新用户界面。此事件从用户界面线程(调度线程)引发,无需Dispatcher。
WorkerSupportsCancellation属性: 需要添加取消支持,就必须设为true。
CancellationPending属性: 检查任务是否被取消。一般在DoWork事件中的循环操作中检查此属性。
CancelAsync()方法: 取消请求。调用此方法不会执行任何取消的行为,只是将CancellationPending属性设为true,表示用户已经取消了任务。
Cancel属性: 设置任务被取消了,以完成取消操作。
1 //BackgroundWorker组件的使用总结: 2 //1.在DoWork事件中处理耗时任务。 3 //2.如果需要进度报告,就将WorkerReportsProgress属性设置为true。在DoWork事件中调用ReportProgress()方法,ReportProgress()可以触发ProgressChanged事件,在ProgressChanged事 件中更新Ui。 4 //3.如果需要取消支持,就将WorkerSupportsCancellation属性设置为true,在其它如按钮事件下执行CancelAsync()方法执行取消。然后在DoWork事件中检查取消请求CancellationPending属性 。如果任务被取消了,就设置Cancel属性为true,以设置任务是被取消才结束的。 5 //4.在RunWorkerCompleted事件中做任务结束的响应处理。 6 //5.通过调用RunWorkerAsync()方法启动。 7 8 public BackgroundWorker backgroundWorker; 9 backgroundWorker.RunWorkerAsync()//启动 10 11 //DoWork事件 12 private void bcakgroundWorker_DoWork(object sender, DoWorkEventArgs e) 13 { 14 //更新进度 15 if(backgroundWorker.WorkerReportsProgress) 16 { 17 backgroundWorker.ReportProgress(50); 18 } 19 20 //检查取消 21 if(backgroundWorker.CancellationPending) 22 { 23 e.Cancel = true; // 设置为取消 24 return; 25 } 26 } 27 28 //RunWorkerCompleted事件 29 private void background_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) 30 { 31 // dosomething. 32 } 33 34 //ProgressChanged事件 35 backgroundWorker_ProgressChanged(object sender, ProgressChangedEventArgs e) 36 { 37 //更新进度条之类的任务 38 } 39 40 //取消 41 private void DoCancel(object sender, RoutedEventArgs e) 42 { 43 backgroundWorker.CancelAsync(); 44 }
基于任务的异步模式:
使用await async关键字,没有阻塞,也不需要切换回UI线程,这些都是自动实现的。
代码在遇到await关键字后,会挂起当前线程,异步执行await的异步方法,不阻塞UI线程响应其它用户请求,当异步方法执行完毕后,再从挂起处继续执行。
详细可以看下面的3。
3.异步编程的基础 (关键字 Task await async 异步方法)
有一个同步方法Greeting(),返回一个字符串。
public string Greeting() { return "hello"; }
定义方法GreetingAsync(),可以使方法异步化。
基于任务的异步模式指在异步方法名后加上Async作为后缀,并返回一个任务。
// Task<string>定义了一个返回字符串的任务 public Task<string> GreetingAsync() { return Task<string>.Run(() => { return "hello"; }); }
//未完待续。。13.3.2调用异步方法
标签:
原文地址:http://www.cnblogs.com/lztwj/p/4639677.html