VS2010是经常阻塞UI线程的应用程序之一。例如用vs2010打开一个包含数百个项目的解决方案,可以要等待很长时间(感觉像卡死),自从vs2012情况得到了改善,项目在后台进行了异步加载。

一、同步模式

二、异步模式

三、基于事件的异步模式

四、基于任务的异步模式

4.5以后更新基于任务的异步模式。

1.最基本的任务

普通方法

        public  string A()
{
return "abc";
}

(1)基于任务的模式带有 Async后缀的方法,并返回一个Task类型。

        public Task<string> AAsync()
{
return Task.Run(() => A());
}

其中Task<string>是一个返回字符串的任务。

用Task.Run方法在线程池上执行一个方法,并返回一个任务对象。

(2)使用关键字await来调用返回的任务 ,await关键字需要用带 Async修饰符的方法声明.

        public async void BAsync()
{
string str = await AAsync();
Console.WriteLine("abc");
}

Async修饰符只能用于返回Task<>或者void的方法。而且Async不能修饰Main。await只能返回Task的方法

完整代码,执行一个异步任务

例1

    class Program
{
static void Main(string[] args)
{
Program p = new Program();
p.BAsync();
Console.ReadKey();
}
public string A()
{
return "abc";
}
public Task<string> AAsync()
{
return Task.Run(() => A());
}
public async void BAsync()
{
string str = await AAsync();
Console.WriteLine("abc");
}
}

任务完成后执行

    class Program
{
static void Main(string[] args)
{
Program p = new Program();
p.C();
Console.ReadKey();
}
public string A()
{
return "abc";
}
public Task<string> AAsync()
{
return Task.Run(() => A());
}
public void C()
{
//用task对象接收返回对象
Task<string> t1 = AAsync();
//任务完成后调用的代码
t1.ContinueWith(t =>
{
Thread.Sleep();
string s = t.Result;
Console.WriteLine(s);
});
Console.WriteLine("efg");
}
}

(3)使用await async关键字,当await完成之后,不需要进行任何特别处理,就能访问UI线程

???

(4)使用多个异步方法

按顺序调用异步

修改例1 的BAsync()方法

        public async void BAsync()
{
string str = await AAsync();
string str2 = await AAsync() + "d";
Console.WriteLine("{0},{1}",str,str2);
}

如果一个异步依赖另一个异步方法的结果,await非常有用,如果完全独立,每个异步方法都不使用await,整个方法将更快返回结果

组合器

一个组合器可以接受多个同一类型的参数,并返回同一类型的值。

        public async void BAsync()
{
Task<string> T1 = AAsync();
Task<string> T2 = AAsync();
//等待,直到两个任务完成,返回task
await Task.WhenAll(T1,T2);
Console.WriteLine("{0},{1}", T1.Result, T2.Result);
//也可用于返回数组
string[] res= await Task.WhenAll(T1, T2);
Console.WriteLine("{0},{1}", res[], res[]);
//其中一个完成就返回task
await Task.WhenAny(T1, T2);
}

(5)转换异步模式

2.错误处理

3.取消

五、委托进行异步编程

1.BeginInvoke()
异步启动委托, 参数与要执行的方法的参数相同,另加两个可选参数
第一个参数是一个 AsyncCallback 委托,此委托引用在异步调用完成时要调用的方法。
第二个参数是一个用户定义的对象,该对象将信息传递到回调方法。
BeginInvoke 将立即返回,而不会等待异步调用完成。
BeginInvoke 返回可用于监视异步调用的进度的 IAsyncResult。
IAsyncResult 对象 =委托对象.BeginInvoke(定义委托时有几个参数,AsyncCallback ,类的对象);

2.EndInvoke()
EndInvoke 方法用于检索异步调用的结果,它可以在调用 BeginInvoke之后的任意时间调用。
如果异步调用尚未完成,那么 EndInvoke 将阻止调用线程,直到完成异步调用。
这种方式非常适合执行文件或网络操作。

(1)使用 EndInvoke 等待异步调用

在控制台下运行

新建了一个测试类,一个用来同步,一个用来异步。

    class Program
{
public delegate string delegateClass(int time);
static void Main(string[] args)
{
TextClass textClass = new TextClass();
//把要执行的异步方法存入委托
delegateClass testMethod = new delegateClass(textClass.asynMethod);
//启动异步委托,参数一有没有取决于定义委托时的参数有没有
IAsyncResult result = testMethod.BeginInvoke(, null, null);
//当异步委托结束后,把该委托返回的值回传给str
string str1 = testMethod.EndInvoke(result);
Console.WriteLine(str1);
Console.WriteLine("...............");
//运行同步方法
string str2 = textClass.synMethod();
Console.WriteLine(str2);
Console.ReadKey();
}
}
//测试类
class TextClass
{
//用来同步
public string synMethod(int time)
{
Console.WriteLine("启动同步方法");
Thread.Sleep(time);
Console.WriteLine("结束同步方法");
return "同步返回";
}
//用来异步
public string asynMethod(int time)
{
Console.WriteLine("启动异步方法");
Thread.Sleep(time);
Console.WriteLine("结束异步方法");
return "异步返回";
}
}

运行结果:

发现结果异步操作执行后,才执行的同步操作。

然后注释掉“等待异步调用的方法”

//string str1 = testMethod.EndInvoke(result);
//Console.WriteLine(str1);

在运行:

EndInvoke()方法会把所在的线程卡住(阻塞)

所以如果在winfrom下运行EndInvoke(),在异步未执行完的条件下会把界面卡死。EndInvoke方法不能和用户界面在同一个线程下。

(2)对异步调用的完成情况进行轮询

        public delegate string delegateClass(int time);
static void Main(string[] args)
{
TextClass textClass = new TextClass();
//把要执行的异步方法存入委托
delegateClass testMethod = new delegateClass(textClass.asynMethod);
//启动异步委托
IAsyncResult result = testMethod.BeginInvoke(, null, null);
//如果异步为执行完成,会不断循环执行此方法。
while (result.IsCompleted == false)
{
//Thread.Sleep(350);
Console.Write("a");
}
//当异步委托结束后,把该委托返回的值回传给str
string str1 = testMethod.EndInvoke(result);
Console.WriteLine(str1);
Console.ReadKey();
}
}
//测试类
class TextClass
{
//用来异步
public string asynMethod(int time)
{
Console.WriteLine("启动异步方法");
Thread.Sleep(time);
Console.WriteLine("b");
Console.WriteLine("结束异步方法");
return "异步返回";
}
}

结果

(3)异步调用完成时执行回调方法

winfrom

    public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
//是否捕获对错误线程的调用
Control.CheckForIllegalCrossThreadCalls = false;
}
//
private delegate string delegatehWeb();
delegatehWeb delWeb=new delegatehWeb(webReuest);
private void button1_Click(object sender, EventArgs e)
{
//执行异步,异步结束后,执行Callback方法
IAsyncResult result = delWeb.BeginInvoke(Callback, null);
textBox1.Text = "HTML代码";
} //回调方法
public void Callback(IAsyncResult result)
{
string str = delWeb.EndInvoke(result);
textBox1.Text = str;
//MessageBox.Show(str);
} //获取网站HTML
public static string webReuest()
{
HttpWebRequest httpWebRequest = WebRequest.CreateHttp("http://www.baidu.com/");
WebResponse httpWebResponse = httpWebRequest.GetResponse();
//返回数据流
Stream stream = httpWebResponse.GetResponseStream();
Encoding encode = Encoding.GetEncoding("utf-8");
StreamReader readStream = new StreamReader(stream, encode);
//把流转成字符串
string htmlStr = readStream.ReadToEnd();
Thread.Sleep();
return htmlStr;
}
}

task 执行异步任务, t.Wait()阻塞所在线程

        private void button1_Click(object sender, EventArgs e)
{
Task t = Task.Run(() => {
Thread.Sleep(3000);
          //所在线程id
MessageBox.Show(Convert.ToString(Thread.CurrentThread.ManagedThreadId));
});
MessageBox.Show(Convert.ToString(Thread.CurrentThread.ManagedThreadId));
//等待task完成后向后执行
t.Wait();
MessageBox.Show(Convert.ToString(Thread.CurrentThread.ManagedThreadId));
}

(41)C#异步编程的更多相关文章

  1. [C#] 走进异步编程的世界 - 剖析异步方法(下)

    走进异步编程的世界 - 剖析异步方法(下) 序 感谢大家的支持,这是昨天发布<走进异步编程的世界 - 剖析异步方法(上)>的补充篇. 目录 异常处理 在调用方法中同步等待任务 在异步方法中 ...

  2. [C#] 走进异步编程的世界 - 在 GUI 中执行异步操作

    走进异步编程的世界 - 在 GUI 中执行异步操作 [博主]反骨仔 [原文地址]http://www.cnblogs.com/liqingwen/p/5877042.html 序 这是继<开始接 ...

  3. JavaScript异步编程的主要解决方案—对不起,我和你不在同一个频率上

    众所周知(这也忒夸张了吧?),Javascript通过事件驱动机制,在单线程模型下,以异步的形式来实现非阻塞的IO操作.这种模式使得JavaScript在处理事务时非常高效,但这带来了很多问题,比如异 ...

  4. 走进异步编程的世界 - 开始接触 async/await

    [C#] 走进异步编程的世界 - 开始接触 async/await   走进异步编程的世界 - 开始接触 async/await 序 这是学习异步编程的入门篇. 涉及 C# 5.0 引入的 async ...

  5. 异步编程 z

    走进异步编程的世界 - 开始接触 async/await 序 这是学习异步编程的入门篇. 涉及 C# 5.0 引入的 async/await,但在控制台输出示例时经常会采用 C# 6.0 的 $&qu ...

  6. [C#] 走进异步编程的世界 - 开始接触 async/await(转)

    原文链接:http://www.cnblogs.com/liqingwen/p/5831951.html 走进异步编程的世界 - 开始接触 async/await 序 这是学习异步编程的入门篇. 涉及 ...

  7. 利用python yielding创建协程将异步编程同步化

    转自:http://www.jackyshen.com/2015/05/21/async-operations-in-form-of-sync-programming-with-python-yiel ...

  8. 异步编程和线程的使用(.NET 4.5 )

    C#:异步编程和线程的使用(.NET 4.5 )   异步编程和线程处理是并发或并行编程非常重要的功能特征.为了实现异步编程,可使用线程也可以不用.将异步与线程同时讲,将有助于我们更好的理解它们的特征 ...

  9. 走进异步编程的世界 - 开始接触 async/await(转)

    序 这是学习异步编程的入门篇. 涉及 C# 5.0 引入的 async/await,但在控制台输出示例时经常会采用 C# 6.0 的 $"" 来拼接字符串,相当于string.Fo ...

随机推荐

  1. 【python】python环境搭建

    本文主要用于记录python环境的搭建一些不常用的命令,其他的安装步骤在其他大师可以找到就不详细列出了.(注:以下操作都是在Ubuntu14.04LTS版本) 一.环境查询相关 1.查询当前pytho ...

  2. 【Maven】 (请使用 -source 8 或更高版本以启用 lambda 表达式)

    在使用mvn install编译maven项目时,报了 “ (请使用 -source 8 或更高版本以启用 lambda 表达式)”错误,是因为设置的maven默认jdk编译版本太低的问题. 可使用两 ...

  3. 数据库储存session信息代码

    今天给大家上一段代码,数据库存储session信息,你只需要将下面这段代码放到session文件中,然后再session_start()的地方引入sessiong文件就行啦,当然你就不用再写sessi ...

  4. zookeeper伪集群(一)

    Zookeeper的安装和配置十分简单, 既可以配置成单机模式, 也可以配置成伪集群模式.集群模式. 本人将对伪集群.集群进行重点介绍: 铺垫: 1.集群必须是奇数(2N+1),伪集群和集群一致. 2 ...

  5. python之路-双下方法

    双下方法 定义: 双下方法是特殊方法,他是解释器提供的,由双下线加方法名加双下划线 __方法名__具有特殊意义的方法 双下方法主要是Python源码程序员使用的,元编程 我们在开发中尽量不要使用双下方 ...

  6. PAT Basic 1074

    1074 宇宙无敌加法器 地球人习惯使用十进制数,并且默认一个数字的每一位都是十进制的.而在 PAT 星人开挂的世界里,每个数字的每一位都是不同进制的,这种神奇的数字称为“PAT数”.每个 PAT 星 ...

  7. cache共享问题

    经测试发现,cache在web中与windows service中是不能共享的.但在windows service可以使用cache.

  8. Selenium WebDriver- 指定页面加载时间

    #encoding=utf-8 import unittest import time from selenium import webdriver from selenium.webdriver i ...

  9. 第四部分 linux使用者管理

    第一章 linux帐号管理与acl权限控制    不同的用户拥有不同的权限    可以通过user/group的特殊权限设定,来规范不同的群组开发 一 linux帐号与群组 A 使用者的识别码: UI ...

  10. X86保护模式 八操作系统类指令

    X86保护模式  八操作系统类指令 通常在操作系统代码中使用,应用程序中不应用这些指令 指令分为三种:实模式指令,任何权级下使用的指令.实模式权级0下可执行的指令和仅在保护模式下执行的指令 一  实模 ...