写了段小代码,给同事演示一下这2个语法糖的代码执行顺序:
class Program
{
static void Main()
{
Msg("Begin");
DisplayValue();
Msg("End");
Console.Read();
}
#region async 测试
public static async Task<double> GetValueAsync(double num1, double num2)
{
Msg("Into GetValueAsync");
var ret = await Task.Run(() =>
{
Msg("Into GetValueAsync Task");
for (int i = 0; i < 1000000; i++)
num1 = num1 / num2;
Msg("out GetValueAsync Task");
return num1;
});
Msg("out GetValueAsync");
return ret;
}
public static async void DisplayValue()
{
Msg("Into DisplayValue");
var result = GetValueAsync(1234.5, 1.01);
Msg("Middle DisplayValue");
Msg("Value is : " + await result);
Msg("Out DisplayValue");
}
#endregion
private static int idx;
static void Msg(string msg)
{
Interlocked.Increment(ref idx);
var id = Thread.CurrentThread.ManagedThreadId.ToString();
Console.WriteLine(idx.ToString() + ". 线程:" + id + " " + msg);
Thread.Sleep(100); // 避免cpu不定,导致顺序打乱
}
}
代码执行结果:
1. 线程:1 Begin
2. 线程:1 Into DisplayValue
3. 线程:1 Into GetValueAsync
4. 线程:1 Middle DisplayValue
5. 线程:3 Into GetValueAsync Task
6. 线程:1 End
7. 线程:3 out GetValueAsync Task
8. 线程:3 out GetValueAsync
9. 线程:3 Value is : 2.47032822920623E-322
10. 线程:3 Out DisplayValue
把GetValueAsync方法的async和await 移除
public static Task<double> GetValueAsync(double num1, double num2)
{
Msg("Into GetValueAsync");
var ret = Task.Run(() =>
{
Msg("Into GetValueAsync Task");
for (int i = 0; i < 1000000; i++)
num1 = num1 / num2;
Msg("out GetValueAsync Task");
return num1;
});
Msg("out GetValueAsync");
return ret;
}
执行顺序就变了,结果如下:
1. 线程:1 Begin
2. 线程:1 Into DisplayValue
3. 线程:1 Into GetValueAsync
4. 线程:1 out GetValueAsync
5. 线程:3 Into GetValueAsync Task
6. 线程:1 Middle DisplayValue
7. 线程:1 End
8. 线程:3 out GetValueAsync Task
9. 线程:3 Value is : 2.47032822920623E-322
10. 线程:3 Out DisplayValue
你看明白了吗?如果不明白,把上面的测试代码复制到你的项目里,改一改,运行一下吧,
简单总结一下:
- await指令调起线程执行异步方法和方法内后面的代码
- await指令会阻塞当前方法后面的代码,但是不会阻塞外部调用
- await必须搭配async使用,而async不一定需要有await