C#之:异步编程 -2

TPL异步模式-续:

1.异步的接口声明

interface ITest
{
	Task<int> GetAsync();//不要标注async
}

class Test : ITest
{
	public async Task<int> GetAsync()
	{
		return 3;
	}	
}

接口中不需要标注 async 但实现类中必须标注 async

2.TPL 异步深入:

有如下异步方法:

 static Task<string> F1Async()
        {
            MessageBox.Show("F1 Start");
            return Task.Run(() => {
                System.Threading.Thread.Sleep(1000);
                MessageBox.Show("F1 Run");
                return "F1";
            });
        }

调用:

  private async void button1_Click(object sender, EventArgs e)
        {
            string i1 = await F1Async();
            MessageBox.Show("i1=" + i1);
        }

Task.Run()一个用来把一个代码段包装为Task的方法Run中委托的代码体就是异步任务执行的逻辑,最后return返回值。
并不是到了await才执行Task异步任务,而是这里是一个“最终保障”
因此不是只有await执行后Task才会真正执行。

总结:

	static Task<string> GetRuPengAsync()
	{
		这里可以return Task<string>类型的值,不能return “a”;
	}
	static async Task<string> GetRuPengAsync()
	{
		这里不可以return Task<string>类型的值,而可以能return “a”;
	}
  1. 只要方法是Task< T >类型的返回值,都可以用await来等待调用获取返回值
  2. 如果一个返回Task< T >类型的方法被标记了async,那么只要方法内部直接return T这个类型的实例就可以。
  3. 一个返回Task类型的方法没有被标记了async,那么需要方法内部直接Task实例。

对于不能标记 async 关键字的方法的异步用法:
下面是一个控制台程序:

 static void Main(string[] args)
        {
            HttpClient hc = new HttpClient();
            Task<HttpResponseMessage> tackMsg = hc.GetAsync("http://www.baidu.com");
            HttpResponseMessage msg = tackMsg.Result;//对于一个Task来讲读取他的Result属性,也是相当于等待任务结束然后获取返回值。
            Task<string> taskRead = msg.Content.ReadAsStringAsync();
            string html = taskRead.Result;
            Console.WriteLine(html);
            Console.ReadKey();
            //F1Async().Result 注意有的上下文下会有死锁。注意:一般不要这样用
        }

1,如果返回值就是一个立即可以随手可得的值,那么就用Task.FromResult()如果是一个需要休息一会的任务(比如下载失败则过5秒钟后重试。主线程不休息,和Thread.Sleep不一样),那么就用Task.Delay()。

2,Task.Factory.FromAsync()把IAsyncResult转换为Task,这样APM风格的api也可以用await来调用。
3,编写异步方法的简化写法。如果方法声明为async,那么可以直接return 具体的值,不再用创建Task,由编译器创建Task:如下面三种写法

static async Task<int> F1Async()
{
	return 1;
}
static Task<int> F2Async()
{
	return Task.FromResult(3);
}

static Task<int> F3Async()
{
	return Task.Run(()=> {
		return 1 + 3;
	});
}

3.TPL异常处理:

1、TPL中,如果程序中出现异常,除非进行try…catch,否则有可能是感觉不到出了异常的。
2,TPL程序有时候还会抛出AggregateException,这通常发生在并行有多个任务执行的情况下。

因为多个并行的任务可能有多个有异常,因此会包装为AggregateException异常AggregateException的 InnerExceptions 属性可以获得多个异常对象信息。

ASP.NET MVC 与 TPL

异步方法不是提升性能,不会提高访问速度,而是提升服务器的“吞吐量”,也就是可以处理的并发请求数得到增加。
返回值改为Task即可,如果方法标记为async,连自己创建Task都省了:
示例:

public async Task<ActionResult> Index()
{
	return View();
}

能用异步方法,就不要用同步方法,可以轻松的提升系统的吞吐量!

异步方法的常见误区:

1、 一定要async到底
一定要让async的传染性(调用异步方法要用await,用了await方法就要声明为async,调用我这个async方法的地方必须要await……)不要轻易直接调用Task的Wait、WaitAll等方法。等待一个用await,而不是task.Wait();等待多个用await Task.WhenAll(),而不是Task.WaitAll()。
2:这样的异步就没有意义:

public async Task<string> GetArticleContentByNoRigntWayAsync()
{
	return await Task.Run(() =>
	{
		using (var client = new WebClient())
		{
			return client.DownloadString("http://www.rupeng.com");//变成同步了
		}
	});
}

用了异步之后就能用异步api就用异步api,只要await、WhenAll,不要task.Result、Wait()、WaitAll()。ADO.Net、IO、EF等都有异步的API。
using System.Data.Entity之后First 之类的也有异步方法

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值