您的位置:首页 > 编程语言

第十节:利用async和await简化异步编程模式的几种写法

2018-01-14 18:51 621 查看
一. async和await简介


PS:简介

1. async和await这两个关键字是为了简化异步编程模型而诞生的,使的异步编程跟简洁,它本身并不创建新线程,但在该方法内部开启多线程,则另算。

2. 这两个关键字适用于处理一些文件IO操作。

3. 好处:代码简介,把异步的代码写成了同步的形式,提高了开发效率。

 坏处:如果使用同步思维去理解,容易出问题,返回值对不上。



二. 几种用法

情况1:当只有async,没有await时,方法会有个警告,和普通的多线程方法没有什么区别,不存在线程等待的问题。

代码实践:

private static async void Test1()
{
//主线程执行
Console.WriteLine("主线程{0}开始:", Thread.CurrentThread.ManagedThreadId);
//启动新线程完成任务
Task task = Task.Run(() =>
{
Console.WriteLine("子线程{0}开始:", Thread.CurrentThread.ManagedThreadId);
Thread.Sleep(3000);
Console.WriteLine("子线程{0}结束:", Thread.CurrentThread.ManagedThreadId);
});
//主线程执行
Console.WriteLine("主线程{0}结束:", Thread.CurrentThread.ManagedThreadId);
}


代码结果:



情况2:不推荐void返回值,使用Task来代替Task和Task<T>能够使用await, Task.WhenAny, Task.WhenAll等方式组合使用,async Void 不行。

代码实践:

/// <summary>
/// 不推荐void返回值,使用Task来代替
/// Task和Task<T>能够使用await, Task.WhenAny, Task.WhenAll等方式组合使用。async Void 不行
/// </summary>
private static async void Test2()
{
//主线程执行
Console.WriteLine("主线程{0}开始:", Thread.CurrentThread.ManagedThreadId);
//启动新线程完成任务
Task task = Task.Run(() =>
{
Console.WriteLine("子线程{0}开始:", Thread.CurrentThread.ManagedThreadId);
Thread.Sleep(3000);
Console.WriteLine("子线程{0}结束:", Thread.CurrentThread.ManagedThreadId);
});
await task;   //等待子线程执行完毕,方可执行后面的语句
Console.WriteLine("主线程{0}结束:", Thread.CurrentThread.ManagedThreadId);
}


代码结果:



情况3:async Task == async void。 区别:Task和Task<T>能够使用await, Task.WhenAny, Task.WhenAll等方式组合使用,async Void 不行。

代码实践:

/// <summary>
/// 无返回值  async Task == async void
/// Task和Task<T>能够使用await, Task.WhenAny, Task.WhenAll等方式组合使用,async Void 不行
/// </summary>
private static async Task Test3()
{
//主线程执行
Console.WriteLine("主线程{0}开始:", Thread.CurrentThread.ManagedThreadId);
//启动新线程完成任务
Task task = Task.Run(() =>
{
Console.WriteLine("子线程{0}开始:", Thread.CurrentThread.ManagedThreadId);
Thread.Sleep(3000);
Console.WriteLine("子线程{0}结束:", Thread.CurrentThread.ManagedThreadId);
});
await task;   //等待子线程执行完毕,方可执行后面的语句
Console.WriteLine("主线程{0}结束:", Thread.CurrentThread.ManagedThreadId);
}


代码结果:



情况4和情况5:说明要使用子线程中的变量,一定要等子线程执行结束后再使用。

代码实践:

/// <summary>
/// 带返回值的Task,要使用返回值,一定要等子线程计算完毕才行
/// </summary>
/// <returns></returns>
private static async Task<long> Test4()
{
//主线程执行
Console.WriteLine("主线程{0}开始:", Thread.CurrentThread.ManagedThreadId);
long result = 0;
//启动新线程完成任务
Task task = Task.Run(() =>
{
for (long i = 0; i < 100; i++)
{
result += i;
}
});
await task;   //等待子线程执行完毕,方可执行后面的语句
Console.WriteLine("主线程{0}结束:", Thread.CurrentThread.ManagedThreadId);
Console.WriteLine("result:{0}", result);
return result;
}


/// <summary>
/// 带返回值的Task,要使用返回值,一定要等子线程计算完毕才行
/// 与情况四形成对比,没有等待,最终结果不准确
/// </summary>
/// <returns></returns>
private static Task<long> Test5()
{
//主线程执行
Console.WriteLine("主线程{0}开始:", Thread.CurrentThread.ManagedThreadId);
long result = 0;
//启动新线程完成任务
TaskFactory taskFactory = new TaskFactory();
Task<long> task = taskFactory.StartNew<long>(() =>
{
for (long i = 0; i < 100; i++)
{
result += i;
}
return 1;
});
Console.WriteLine("主线程{0}结束:", Thread.CurrentThread.ManagedThreadId);
Console.WriteLine("result:{0}", result);
return task;
}


代码结果:

  以上两种情况,第一种情况含有线程等待的结果为4950,第二个情况么有线程等待,结果不准确(即共享变量竞用问题)。

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: