class Program
{
static void Main(string[] args)
{
Console.WriteLine("我是主线程,线程ID:{0}", Thread.CurrentThread.ManagedThreadId);
TestAsync();
Console.WriteLine("我是主线程,调用TestAsync之后,线程ID:{0}", Thread.CurrentThread.ManagedThreadId);
Console.ReadLine();
}
static void TestAsync()
{
Console.WriteLine("调用GetReturnResult()之前,线程ID:{0}。当前时间:{1}", Thread.CurrentThread.ManagedThreadId, DateTime.Now.ToString("yyyy-MM-dd hh:MM:ss"));
var name = GetReturnResult();
Console.WriteLine("调用GetReturnResult()之后,线程ID:{0}。当前时间:{1}", Thread.CurrentThread.ManagedThreadId, DateTime.Now.ToString("yyyy-MM-dd hh:MM:ss"));
Console.WriteLine("得到GetReturnResult()方法的结果:{0}。当前时间:{1}。线程Id:{2}", name, DateTime.Now.ToString("yyyy-MM-dd hh:MM:ss"),Thread.CurrentThread.ManagedThreadId);
Console.WriteLine("得到返回值后,线程ID:{0}。当前时间:{1}", Thread.CurrentThread.ManagedThreadId, DateTime.Now.ToString("yyyy-MM-dd hh:MM:ss"));
}
static async Task<string> GetReturnResult()
{
Console.WriteLine("执行Task.Run之前, 线程ID:{0}", Thread.CurrentThread.ManagedThreadId);
return await Task.Run(() =>
{
Thread.Sleep(300);
Console.WriteLine("GetReturnResult()方法里面线程ID: {0}", Thread.CurrentThread.ManagedThreadId);
return "我是返回值";
});
}
}
执行结果:
我是主线程,线程ID:1
调用GetReturnResult()之前,线程ID:1。当前时间:2018-07-27 03:07:25
执行Task.Run之前, 线程ID:1
调用GetReturnResult()之后,线程ID:1。当前时间:2018-07-27 03:07:25
得到GetReturnResult()方法的结果:System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1+AsyncStateMachineBox`1[System.String,ConsoleApp1.Program+<GetReturnResult>d__2]。当前时间:2018-07-27 03:07:25。线程Id:1
得到返回值后,线程ID:1。当前时间:2018-07-27 03:07:25
我是主线程,调用TestAsync之后,线程ID:1
GetReturnResult()方法里面线程ID: 3
结论:
TestAsync内的语句顺序执行,
name是空,也会直接返回,并不会等待得到name的结果。
class Program
{
static void Main(string[] args)
{
Console.WriteLine("我是主线程,线程ID:{0}", Thread.CurrentThread.ManagedThreadId);
TestAsync();
Console.WriteLine("我是主线程,调用TestAsync之后,线程ID:{0}", Thread.CurrentThread.ManagedThreadId);
Console.ReadLine();
}
static void TestAsync()
{
Console.WriteLine("调用GetReturnResult()之前,线程ID:{0}。当前时间:{1}", Thread.CurrentThread.ManagedThreadId, DateTime.Now.ToString("yyyy-MM-dd hh:MM:ss"));
var name = GetReturnResult();
Console.WriteLine("调用GetReturnResult()之后,线程ID:{0}。当前时间:{1}", Thread.CurrentThread.ManagedThreadId, DateTime.Now.ToString("yyyy-MM-dd hh:MM:ss"));
Console.WriteLine("得到GetReturnResult()方法的结果:{0}。当前时间:{1}。线程Id:{2}", name, DateTime.Now.ToString("yyyy-MM-dd hh:MM:ss"),Thread.CurrentThread.ManagedThreadId);
Console.WriteLine("得到返回值后,线程ID:{0}。当前时间:{1}", Thread.CurrentThread.ManagedThreadId, DateTime.Now.ToString("yyyy-MM-dd hh:MM:ss"));
}
static Task<string> GetReturnResult()
{
Console.WriteLine("执行Task.Run之前, 线程ID:{0}", Thread.CurrentThread.ManagedThreadId);
return Task.Run(() =>
{
Thread.Sleep(300);
Console.WriteLine("GetReturnResult()方法里面线程ID: {0}", Thread.CurrentThread.ManagedThreadId);
return "我是返回值";
});
}
}
执行结果:
我是主线程,线程ID:1
调用GetReturnResult()之前,线程ID:1。当前时间:2018-07-27 04:07:46
执行Task.Run之前, 线程ID:1
调用GetReturnResult()之后,线程ID:1。当前时间:2018-07-27 04:07:46
得到GetReturnResult()方法的结果:System.Threading.Tasks.Task`1[System.String]。当前时间:2018-07-27 04:07:46。线程Id:1
得到返回值后,线程ID:1。当前时间:2018-07-27 04:07:46
我是主线程,调用TestAsync之后,线程ID:1
GetReturnResult()方法里面线程ID: 3
结论:
和第一种情况一样。
class Program
{
static void Main(string[] args)
{
Console.WriteLine("我是主线程,线程ID:{0}", Thread.CurrentThread.ManagedThreadId);
TestAsync();
Console.WriteLine("我是主线程,调用TestAsync之后,线程ID:{0}", Thread.CurrentThread.ManagedThreadId);
Console.ReadLine();
}
static async Task TestAsync()
{
Console.WriteLine("调用GetReturnResult()之前,线程ID:{0}。当前时间:{1}", Thread.CurrentThread.ManagedThreadId, DateTime.Now.ToString("yyyy-MM-dd hh:MM:ss"));
var name = GetReturnResult();
Console.WriteLine("调用GetReturnResult()之后,线程ID:{0}。当前时间:{1}", Thread.CurrentThread.ManagedThreadId, DateTime.Now.ToString("yyyy-MM-dd hh:MM:ss"));
Console.WriteLine("得到GetReturnResult()方法的结果:{0}。当前时间:{1}。线程Id:{2}", await name, DateTime.Now.ToString("yyyy-MM-dd hh:MM:ss"),Thread.CurrentThread.ManagedThreadId);
Console.WriteLine("得到返回值后,线程ID:{0}。当前时间:{1}", Thread.CurrentThread.ManagedThreadId, DateTime.Now.ToString("yyyy-MM-dd hh:MM:ss"));
}
static async Task<string> GetReturnResult()
{
Console.WriteLine("执行Task.Run之前, 线程ID:{0}", Thread.CurrentThread.ManagedThreadId);
return await Task.Run(() =>
{
Thread.Sleep(300);
Console.WriteLine("GetReturnResult()方法里面线程ID: {0}", Thread.CurrentThread.ManagedThreadId);
return "我是返回值";
});
}
}
执行结果:
我是主线程,线程ID:1
调用GetReturnResult()之前,线程ID:1。当前时间:2018-07-27 04:07:27
执行Task.Run之前, 线程ID:1
调用GetReturnResult()之后,线程ID:1。当前时间:2018-07-27 04:07:27
我是主线程,调用TestAsync之后,线程ID:1
GetReturnResult()方法里面线程ID: 3
得到GetReturnResult()方法的结果:我是返回值。当前时间:2018-07-27 04:07:28。线程Id:3
得到返回值后,线程ID:3。当前时间:2018-07-27 04:07:28
结论:
1,打印name时,会等待name返回回来,后面的语句不会执行,线程阻塞在这里,返回值后,继续执行,但是在id为3的线程里执行
2,主线程调用TestAsync();,因为没有返回值,主线程会进入TestAsync函数内,依次执行,直到遇到await,主线程不会继续执行await之后的语句,而是跳出这个函数,继续执行TestAsync();之后的语句。那么TestAsync()如果有返回值会怎么样呢,下面就来测试。
class Program
{
static void Main(string[] args)
{
Console.WriteLine("我是主线程,线程ID:{0}", Thread.CurrentThread.ManagedThreadId);
Task<string> name= TestAsync();
Console.WriteLine("我是主线程,调用TestAsync之后,线程ID:{0}", Thread.CurrentThread.ManagedThreadId);
Console.WriteLine("我是主线程,调用TestAsync之后,结果:{0},线程ID:{1}", name.Result, Thread.CurrentThread.ManagedThreadId);
Console.ReadLine();
}
static async Task<string> TestAsync()
{
Console.WriteLine("调用GetReturnResult()之前,线程ID:{0}。当前时间:{1}", Thread.CurrentThread.ManagedThreadId, DateTime.Now.ToString("yyyy-MM-dd hh:MM:ss"));
Task<string> name = GetReturnResult();
Console.WriteLine("调用GetReturnResult()之后,线程ID:{0}。当前时间:{1}", Thread.CurrentThread.ManagedThreadId, DateTime.Now.ToString("yyyy-MM-dd hh:MM:ss"));
Console.WriteLine("得到GetReturnResult()方法的结果:{0}。当前时间:{1}。线程Id:{2}", await name, DateTime.Now.ToString("yyyy-MM-dd hh:MM:ss"),Thread.CurrentThread.ManagedThreadId);
Console.WriteLine("得到返回值后,线程ID:{0}。当前时间:{1}", Thread.CurrentThread.ManagedThreadId, DateTime.Now.ToString("yyyy-MM-dd hh:MM:ss"));
return name.Result;
}
static async Task<string> GetReturnResult()
{
Console.WriteLine("执行Task.Run之前, 线程ID:{0}", Thread.CurrentThread.ManagedThreadId);
return await Task.Run(() =>
{
Thread.Sleep(300);
Console.WriteLine("GetReturnResult()方法里面线程ID: {0}", Thread.CurrentThread.ManagedThreadId);
return "我是返回值";
});
}
}
执行结果:
我是主线程,线程ID:1
调用GetReturnResult()之前,线程ID:1。当前时间:2018-07-27 04:07:35
执行Task.Run之前, 线程ID:1
调用GetReturnResult()之后,线程ID:1。当前时间:2018-07-27 04:07:35
我是主线程,调用TestAsync之后,线程ID:1
GetReturnResult()方法里面线程ID: 3
得到GetReturnResult()方法的结果:我是返回值。当前时间:2018-07-27 04:07:35。线程Id:3
得到返回值后,线程ID:3。当前时间:2018-07-27 04:07:35
我是主线程,调用TestAsync之后,结果:我是返回值,线程ID:1
结论:
2,主线程调用TestAsync();,主线程会进入TestAsync函数内,依次执行,执行到GetReturnResult();,遇到await,退出该函数,继续向下执行,又遇到await name,主线程不会继续执行await之后的语句,而是跳出这个函数,继续执行TestAsync();之后的语句。遇到name,因为name没有赋值,因此阻塞在这里。那么问题来了,第一种情况的时候,TestAsync没有async,await时,name会直接打印出一些乱七八糟的东西,而main函数同样也没有,但是执行结果却不一样,这是为什么呢?那么测试一下第一种情况里,var name改成 和上面一样的Task<string> name,测试以下。
class Program
{
static void Main(string[] args)
{
Console.WriteLine("我是主线程,线程ID:{0}", Thread.CurrentThread.ManagedThreadId);
TestAsync();
Console.WriteLine("我是主线程,调用TestAsync之后,线程ID:{0}", Thread.CurrentThread.ManagedThreadId);
Console.ReadLine();
}
static void TestAsync()
{
Console.WriteLine("调用GetReturnResult()之前,线程ID:{0}。当前时间:{1}", Thread.CurrentThread.ManagedThreadId, DateTime.Now.ToString("yyyy-MM-dd hh:MM:ss"));
Task<string> name = GetReturnResult();
Console.WriteLine("调用GetReturnResult()之后,线程ID:{0}。当前时间:{1}", Thread.CurrentThread.ManagedThreadId, DateTime.Now.ToString("yyyy-MM-dd hh:MM:ss"));
Console.WriteLine("得到GetReturnResult()方法的结果:{0}。当前时间:{1}。线程Id:{2}", name.Result, DateTime.Now.ToString("yyyy-MM-dd hh:MM:ss"), Thread.CurrentThread.ManagedThreadId);
Console.WriteLine("得到返回值后,线程ID:{0}。当前时间:{1}", Thread.CurrentThread.ManagedThreadId, DateTime.Now.ToString("yyyy-MM-dd hh:MM:ss"));
}
static async Task<string> GetReturnResult()
{
Console.WriteLine("执行Task.Run之前, 线程ID:{0}", Thread.CurrentThread.ManagedThreadId);
return await Task.Run(() =>
{
Thread.Sleep(300);
Console.WriteLine("GetReturnResult()方法里面线程ID: {0}", Thread.CurrentThread.ManagedThreadId);
return "我是返回值";
});
}
}
执行结果:
我是主线程,线程ID:1
调用GetReturnResult()之前,线程ID:1。当前时间:2018-07-27 04:07:19
执行Task.Run之前, 线程ID:1
调用GetReturnResult()之后,线程ID:1。当前时间:2018-07-27 04:07:19
GetReturnResult()方法里面线程ID: 3
得到GetReturnResult()方法的结果:我是返回值。当前时间:2018-07-27 04:07:19。线程Id:1
得到返回值后,线程ID:1。当前时间:2018-07-27 04:07:19
我是主线程,调用TestAsync之后,线程ID:1
结论:
1,第一种情况,var name和Task<string> name,执行的结果不同。
分析:
1.1var name,直接打印的name,打印出来的是Task类型,所以这里不会阻塞,直接执行
1.2Task<string> name,打印的name.Result,打印的是Task的结果,因为结果没出来,所以会阻塞。
1.3Task<string> name,打印的name.Result和第三种情况, static async Task TestAsync() 打印 await name。
相同点:两者都会阻塞线程
不同点:
name.Result会阻塞主线程,直到线程3执行完,返回值后,主线程1才会在name.Result处继续执行
await name不会阻塞主线程,线程3在没有回值值的情况下,直接在await处跳出TestAsync函数,继续执行TestAsync();语句后面的下一个语句。当线程3返回值后,会由线程3去执行await name语句和它之后的语句。
这里有个疑问,如果不开线程3会怎么样?那就测试以下:
class Program
{
static void Main(string[] args)
{
Console.WriteLine("我是主线程,线程ID:{0}", Thread.CurrentThread.ManagedThreadId);
TestAsync();
Console.WriteLine("我是主线程,调用TestAsync之后,线程ID:{0}", Thread.CurrentThread.ManagedThreadId);
Console.ReadLine();
}
static void TestAsync()
{
Console.WriteLine("调用GetReturnResult()之前,线程ID:{0}。当前时间:{1}", Thread.CurrentThread.ManagedThreadId, DateTime.Now.ToString("yyyy-MM-dd hh:MM:ss"));
Task<string> name = GetReturnResult();
Console.WriteLine("调用GetReturnResult()之后,线程ID:{0}。当前时间:{1}", Thread.CurrentThread.ManagedThreadId, DateTime.Now.ToString("yyyy-MM-dd hh:MM:ss"));
Console.WriteLine("得到GetReturnResult()方法的结果:{0}。当前时间:{1}。线程Id:{2}", name.Result, DateTime.Now.ToString("yyyy-MM-dd hh:MM:ss"), Thread.CurrentThread.ManagedThreadId);
Console.WriteLine("得到返回值后,线程ID:{0}。当前时间:{1}", Thread.CurrentThread.ManagedThreadId, DateTime.Now.ToString("yyyy-MM-dd hh:MM:ss"));
}
static async Task<string> GetReturnResult()
{
Console.WriteLine("执行GetReturnResult之前, 线程ID:{0}", Thread.CurrentThread.ManagedThreadId);
//return await Task.Run(() =>
//{
// Thread.Sleep(300);
// Console.WriteLine("GetReturnResult()方法里面线程ID: {0}", Thread.CurrentThread.ManagedThreadId);
// return "我是返回值";
//});
return await GetReturnResult1();
}
static async Task<string> GetReturnResult1()
{
Console.WriteLine("执行GetReturnResult1之前, 线程ID:{0}", Thread.CurrentThread.ManagedThreadId);
Thread.Sleep(300);
Console.WriteLine("GetReturnResult1()方法里面线程ID: {0}", Thread.CurrentThread.ManagedThreadId);
return "我是返回值";
}
}
执行结果:
我是主线程,线程ID:1
调用GetReturnResult()之前,线程ID:1。当前时间:2018-07-27 05:07:11
执行GetReturnResult之前, 线程ID:1
执行GetReturnResult1之前, 线程ID:1
GetReturnResult1()方法里面线程ID: 1
调用GetReturnResult()之后,线程ID:1。当前时间:2018-07-27 05:07:11
得到GetReturnResult()方法的结果:我是返回值。当前时间:2018-07-27 05:07:11。线程Id:1
得到返回值后,线程ID:1。当前时间:2018-07-27 05:07:11
我是主线程,调用TestAsync之后,线程ID:1
结论:
1,不开线程3,那么会顺序执行,await也就不起什么作用了,和没有await执行顺序一样
2,不开线程是因为GetReturnResult1方法里没有await ,在耗时操作前加await就会自动开启线程,而不需要开发者自己开线程。所以接着测试
class Program
{
static void Main(string[] args)
{
Console.WriteLine("我是主线程,线程ID:{0}", Thread.CurrentThread.ManagedThreadId);
TestAsync();
Console.WriteLine("我是主线程,调用TestAsync之后,线程ID:{0}", Thread.CurrentThread.ManagedThreadId);
Console.ReadLine();
}
static void TestAsync()
{
Console.WriteLine("调用GetReturnResult()之前,线程ID:{0}。当前时间:{1}", Thread.CurrentThread.ManagedThreadId, DateTime.Now.ToString("yyyy-MM-dd hh:MM:ss"));
Task<string> name = GetReturnResult();
Console.WriteLine("调用GetReturnResult()之后,线程ID:{0}。当前时间:{1}", Thread.CurrentThread.ManagedThreadId, DateTime.Now.ToString("yyyy-MM-dd hh:MM:ss"));
Console.WriteLine("得到GetReturnResult()方法的结果:{0}。当前时间:{1}。线程Id:{2}", name.Result, DateTime.Now.ToString("yyyy-MM-dd hh:MM:ss"), Thread.CurrentThread.ManagedThreadId);
Console.WriteLine("得到返回值后,线程ID:{0}。当前时间:{1}", Thread.CurrentThread.ManagedThreadId, DateTime.Now.ToString("yyyy-MM-dd hh:MM:ss"));
}
static async Task<string> GetReturnResult()
{
Console.WriteLine("执行GetReturnResult之前, 线程ID:{0}", Thread.CurrentThread.ManagedThreadId);
//return await Task.Run(() =>
//{
// Thread.Sleep(300);
// Console.WriteLine("GetReturnResult()方法里面线程ID: {0}", Thread.CurrentThread.ManagedThreadId);
// return "我是返回值";
//});
GetReturnResult1();
GetReturnResult1();
return await GetReturnResult1();
}
static async Task<string> GetReturnResult1()
{
Console.WriteLine("执行GetReturnResult1之前, 线程ID:{0}", Thread.CurrentThread.ManagedThreadId);
TaskCompletionSource<string> tcs = new TaskCompletionSource<string>();
await Task.Delay(1000); //模拟耗时操作
Console.WriteLine("GetReturnResult1()方法里面模拟耗时操作线程ID: {0}", Thread.CurrentThread.ManagedThreadId);
Console.WriteLine("GetReturnResult1()方法里面线程ID: {0}", Thread.CurrentThread.ManagedThreadId);
return "我是返回值";
}
}
执行结果:
我是主线程,线程ID:1
调用GetReturnResult()之前,线程ID:1。当前时间:2018-07-28 03:07:18
执行GetReturnResult之前, 线程ID:1
执行GetReturnResult1之前, 线程ID:1
执行GetReturnResult1之前, 线程ID:1
执行GetReturnResult1之前, 线程ID:1
调用GetReturnResult()之后,线程ID:1。当前时间:2018-07-28 03:07:18
GetReturnResult1()方法里面模拟耗时操作线程ID: 4
GetReturnResult1()方法里面线程ID: 4
GetReturnResult1()方法里面模拟耗时操作线程ID: 6
GetReturnResult1()方法里面线程ID: 6
得到GetReturnResult()方法的结果:我是返回值。当前时间:2018-07-28 03:07:19。线程Id:1
GetReturnResult1()方法里面模拟耗时操作线程ID: 5
GetReturnResult1()方法里面线程ID: 5
得到返回值后,线程ID:1。当前时间:2018-07-28 03:07:19
我是主线程,调用TestAsync之后,线程ID:1
class Program
{
static void Main(string[] args)
{
Console.WriteLine("我是主线程,线程ID:{0}", Thread.CurrentThread.ManagedThreadId);
TestAsync();
Console.WriteLine("我是主线程,调用TestAsync之后,线程ID:{0}", Thread.CurrentThread.ManagedThreadId);
Console.ReadLine();
}
static void TestAsync()
{
Console.WriteLine("调用GetReturnResult()之前,线程ID:{0}。当前时间:{1}", Thread.CurrentThread.ManagedThreadId, DateTime.Now.ToString("yyyy-MM-dd hh:MM:ss"));
Task<string> name = GetReturnResult();
Console.WriteLine("调用GetReturnResult()之后,线程ID:{0}。当前时间:{1}", Thread.CurrentThread.ManagedThreadId, DateTime.Now.ToString("yyyy-MM-dd hh:MM:ss"));
Console.WriteLine("得到GetReturnResult()方法的结果:{0}。当前时间:{1}。线程Id:{2}", name.Result, DateTime.Now.ToString("yyyy-MM-dd hh:MM:ss"), Thread.CurrentThread.ManagedThreadId);
Console.WriteLine("得到返回值后,线程ID:{0}。当前时间:{1}", Thread.CurrentThread.ManagedThreadId, DateTime.Now.ToString("yyyy-MM-dd hh:MM:ss"));
}
static async Task<string> GetReturnResult()
{
Console.WriteLine("执行GetReturnResult之前, 线程ID:{0}", Thread.CurrentThread.ManagedThreadId);
//return await Task.Run(() =>
//{
// Thread.Sleep(300);
// Console.WriteLine("GetReturnResult()方法里面线程ID: {0}", Thread.CurrentThread.ManagedThreadId);
// return "我是返回值";
//});
await GetReturnResult1();
await GetReturnResult1();
return await GetReturnResult1();
}
static async Task<string> GetReturnResult1()
{
Console.WriteLine("执行GetReturnResult1之前, 线程ID:{0}", Thread.CurrentThread.ManagedThreadId);
TaskCompletionSource<string> tcs = new TaskCompletionSource<string>();
await Task.Delay(1000); //模拟耗时操作
Console.WriteLine("GetReturnResult1()方法里面模拟耗时操作线程ID: {0}", Thread.CurrentThread.ManagedThreadId);
Console.WriteLine("GetReturnResult1()方法里面线程ID: {0}", Thread.CurrentThread.ManagedThreadId);
return "我是返回值";
}
}
执行结果:
我是主线程,线程ID:1
调用GetReturnResult()之前,线程ID:1。当前时间:2018-07-28 03:07:57
执行GetReturnResult之前, 线程ID:1
执行GetReturnResult1之前, 线程ID:1
调用GetReturnResult()之后,线程ID:1。当前时间:2018-07-28 03:07:57
GetReturnResult1()方法里面模拟耗时操作线程ID: 4
GetReturnResult1()方法里面线程ID: 4
执行GetReturnResult1之前, 线程ID:4
GetReturnResult1()方法里面模拟耗时操作线程ID: 4
GetReturnResult1()方法里面线程ID: 4
执行GetReturnResult1之前, 线程ID:4
GetReturnResult1()方法里面模拟耗时操作线程ID: 4
GetReturnResult1()方法里面线程ID: 4
得到GetReturnResult()方法的结果:我是返回值。当前时间:2018-07-28 03:07:00。线程Id:1
得到返回值后,线程ID:1。当前时间:2018-07-28 03:07:00
我是主线程,调用TestAsync之后,线程ID:1
结论:
结论:
1,await Task.Delay(1000); //模拟耗时操作,在耗时操作Task.Delay(1000);前加await就会自动开启线程
2,await GetReturnResult1();
await GetReturnResult1();,这两个测试,只有这里第一个代码没有await。
没有await就不会等待线程结束,而是直接另开线程去处理,有await就会等待,上一个线程结束,接着执行。
1,Task在处理不需要返回值时,可以处理多线程,但是如果需要拿到返回值,并不会达到多线程的效果,主线程会被阻塞,因此如果想要得到返回值Task.Result,而且不阻塞主线程,就不能单独用Task来做。而要用async await
2,在处理多线程,不管有没有返回值 async await都不会阻塞主线程,在await处会由分线程来继续执行,而主线程会跳出有await的函数,继续向下执行,达到多线程目的
3,说明即使没有执行Task.Run()去开线程,使用await会在耗时处,系统自动开线程去处理