(1)async和await配套使用,返回值为void
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace ConsoleApp1
{
class Program
{
static void Main(string[] args)
{
Program pr = new Program();
Console.WriteLine("主线程开始---------------");
pr.TestVoidAsync();
Console.WriteLine("主线程结束---------------");
Console.ReadLine();
}
private async void TestVoidAsync()
{
Console.WriteLine("开始执行TestVoidAsync方法");
Task task = new Task(() =>
{
Console.WriteLine("开始子线程耗时操作");
Thread.Sleep(3000);
Console.WriteLine("结束子线程耗时操作");
});
task.Start();
await task;
Console.WriteLine("await关键字后面的内容 1");
Console.WriteLine("await关键字后面的内容 2");
}
}
}
我们会发现,使用await后,执行到await,主线程就是返回去做自己的事情,而await后面的内容将会在子线程执行完成后再继续完成。
await的作用和ContinueWith的作用类似,可以在上一任务以后接下一个任务,并且不会阻塞主线程。
(2)async和await配套使用,返回值Task
- async Task 等效于 async void
- 但是返回Task ,可以使用await,并且可以与Task.WhenAny, Task.WhenAll ContinueWith等组合使用,Void不可以
- 建议使用async Task 这种形式(除事件处理程序外)
写法与async void 相比,没有什么太大的不一样,只是将void ,更换为Task而已,但是返回Task,可以使用await 以及一些Task的方法,如Task.WhenAny, Task.WhenAll ContinueWith等,更有利于后续逻辑的扩展。
如:我们可以在返回Task的方法执行完后使用ContinueWith 再接一个执行任务。
public void TestTask()
{
var task = TestTaskAsync();
task.ContinueWith((t) =>
{
Debug.WriteLine("这里是接着TestTaskAsync方法的执行代码。。。");
});
}
在Main函数中调用 TestTask()即可;
(3)async和await配套使用,返回值Task<T>
- 如果async和await配套使用的时候,需要返回值,则必须通过Task<T>的形式返回值
- 如果不是,编译器会操作,如下图所示
private async Task<int> TestTaskIntAsync()
{
Debug.WriteLine("开始执行TestTaskAsync方法");
int result = 0;
Task task = new Task(() =>
{
Debug.WriteLine("开始子线程耗时操作");
Thread.Sleep(4000);
Debug.WriteLine("结束子线程耗时操作");
result = 10;
});
task.Start();
await task;
Debug.WriteLine("await关键字后面的内容 1");
Debug.WriteLine("await关键字后面的内容 2");
return result;
}
该方法与我们平常返回一个int值的方法没什么太大区别,不过是多了async 和 await ,那么下面将演示如何取出异步方法的返回值。
//方法一:使用ContinueWith
private void button4_Click(object sender, EventArgs e)
{
Task<int> task = TestTaskIntAsync();
task.ContinueWith((t) =>
{
//不能使用Sleep()来阻碍线程,会取不到值
//Thread.Sleep(1000);
Debug.WriteLine($"TestTaskIntAsync的返回值是:{t.Result.ToString()}");
});
}
//方法二:使用await
private async void button4_Click(object sender, EventArgs e)
{
Task<int> task = TestTaskIntAsync();
await task;
Debug.WriteLine($"TestTaskIntAsync的返回值是:{task.Result.ToString()}");
}
(4)不使用async和await,返回值Task<T>
- 之所以列举出来是需要注意区别使用async和await 返回的Task<T> 和不使用async和await 返回Task<T>
private Task<int> TestTaskInt()
{
Debug.WriteLine("开始执行TestTaskAsync方法");
Task<int> task = new Task<int>(() =>
{
Debug.WriteLine("开始子线程耗时操作");
Thread.Sleep(4000);
Debug.WriteLine("结束子线程耗时操作");
int result = 10;//模拟有返回值
return result;
});
task.Start();
return task;
}
//调用,获取返回值
private void button4_Click(object sender, EventArgs e)
{
var task = TestTaskInt();
task.ContinueWith((t)=>
{
Debug.WriteLine(t.Result.ToString());
});
}
(5)使用Async和Await实现多任务顺序执行且不阻塞
1.同步执行
using System;
using System.Diagnostics;
using System.Threading;
using System.Threading.Tasks;
namespace ThreadTest
{
class Program
{
static void Main(string[] args)
{
Stopwatch stopwatch = new Stopwatch();
stopwatch.Start();
PourOJ();
PourCoffee();
ToastBread();
FryBacon();
FryEggs();
Console.WriteLine("早餐已经做完!");
stopwatch.Stop();
Console.WriteLine($"做早餐总计耗时:{stopwatch.ElapsedMilliseconds}");
Console.ReadLine();
}
//倒橙汁
private static void PourOJ()
{
Thread.Sleep(1000);
Console.WriteLine("倒一杯橙汁");
}
//烤面包
private static void ToastBread()
{
Console.WriteLine("开始烤面包");
Thread.Sleep(3000);
Console.WriteLine("烤面包好了");
}
//煎培根
private static void FryBacon()
{
Console.WriteLine("开始煎培根");
Thread.Sleep(6000);
Console.WriteLine("培根煎好了");
}
//煎鸡蛋
private static void FryEggs()
{
Console.WriteLine("开始煎鸡蛋");
Thread.Sleep(6000);
Console.WriteLine("鸡蛋好了");
}
//倒咖啡
private static void PourCoffee()
{
Thread.Sleep(1000);
Console.WriteLine("倒咖啡");
}
}
}
2、异步并行
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Threading;
using System.Threading.Tasks;
namespace ThreadTest
{
class Program
{
static void Main(string[] args)
{
Test();
Console.ReadLine();
}
private static void Test()
{
Stopwatch stopwatch = new Stopwatch();
stopwatch.Start();
List<Task> tasks = new List<Task>() { PourOJ(), ToastBread(), FryBacon(), FryEggs(), PourCoffee() };
Task.WhenAll(tasks).ContinueWith((t)=>
{
Console.WriteLine("早餐已经做完!");
stopwatch.Stop();
Console.WriteLine($"做早餐总计耗时:{stopwatch.ElapsedMilliseconds}");
});
}
//倒橙汁
private static async Task PourOJ()
{
await Task.Delay(1000);
Console.WriteLine("倒一杯橙汁");
}
//烤面包
private static async Task ToastBread()
{
Console.WriteLine("开始烤面包");
await Task.Delay(3000);
Console.WriteLine("烤面包好了");
}
//煎培根
private static async Task FryBacon()
{
Console.WriteLine("开始煎培根");
await Task.Delay(6000);
Console.WriteLine("培根煎好了");
}
//煎鸡蛋
private static async Task FryEggs()
{
Console.WriteLine("开始煎鸡蛋");
await Task.Delay(6000);
Console.WriteLine("鸡蛋好了");
}
//倒咖啡
private static async Task PourCoffee()
{
await Task.Delay(1000);
Console.WriteLine("倒咖啡");
}
}
}
3、并行且可指定顺序执行
private static async void Test()
{
Stopwatch stopwatch = new Stopwatch();
stopwatch.Start();
await PourOJ();
await PourCoffee();
List<Task> tasks = new List<Task>() { ToastBread(), FryBacon(), FryEggs() };
await Task.WhenAll(tasks);
Console.WriteLine("早餐已经做完!");
stopwatch.Stop();
Console.WriteLine($"做早餐总计耗时:{stopwatch.ElapsedMilliseconds}");
}