码迷,mamicode.com
首页 > 编程语言 > 详细

异步编程、线程和任务

时间:2015-07-12 01:39:02      阅读:211      评论:0      收藏:0      [点我收藏+]

标签:

用鼠标操作,我们习惯了延迟,过去几十年都是这样。有了触摸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 }
View Code

 

调度程序提供了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 }
View Code

 

基于任务的异步模式:

使用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

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!