在系统中单开线程进行操作,经常用到Task,发现Task主要有以下两种方法
Task.Factory.StartNew(() => { });
Task.Run(() => { });
初识不知其中区别,特意参考其他文章已做总结https://www.mgenware.com/blog/?p=338
首先说明Task.UnWrap的基本使用
这个扩展方法定义在TaskExtensions类型中,命名空间在System.Threading.Tasks。Unwrap会把嵌套的Task<Task>或者Task<Task<T>>的结果提取出来。
就像这样,不用Unwrap的话:
1 static void Main(string[] args) 2 { 3 doo(); 4 Task.Delay(-1).Wait(); 5 } 6 7 static async void doo() 8 { 9 //运行嵌套的Task 10 //Task返回Task<Task<string>> 11 //第一个await后result类型为Task<string> 12 var result = await Task.Run<Task<string>>(() => 13 { 14 var task = Task.Run<string>(() => 15 { 16 Task.Delay(1000).Wait(); 17 return "Mgen"; 18 }); 19 return task; 20 }); 21 22 //第二个await后才会返回string 23 Console.WriteLine(await result); 24 }
使用Unwrap后,结果可以直接从嵌套Task中提取出来:
1 static async void doo() 2 { 3 //运行嵌套的Task 4 //Task返回Task<Task<string>> 5 //await后类型为Task<string>,Unwrap后result类型为string 6 var result = await Task.Run<Task<string>>(() => 7 { 8 var task = Task.Run<string>(() => 9 { 10 Task.Delay(1000).Wait(); 11 return "Mgen"; 12 }); 13 return task; 14 }).Unwrap(); 15 16 //不需要await,result已经是string 17 Console.WriteLine(result); 18 }
简单地讲,Task.Factory.StartNew和Task.Run区别之一就有Task.Run会自动执行Unwrap操作,但是Task.Factory.StartNew不会,Task.Run就是Task.Factory.StartNew的更人性化封装,而Task.Factory.StartNew则是原始的执行。
通过代码来验证:
1 var task1 = Task.Factory.StartNew(async () => "Mgen"); 2 var task2 = Task.Run(async () => "Mgen"); 3 4 Console.WriteLine(task1.GetType()); 5 Console.WriteLine(task2.GetType());
输出
1 System.Threading.Tasks.Task`1[System.Threading.Tasks.Task`1[System.String]] 2 System.Threading.Tasks.UnwrapPromise`1[System.String]
可以看到
使用Task.Factory.StartNew会返回原始的Task<Task<string>>。但是Task.Run则会直接返回async Lambda的结果,中间的Unwrap操作会自动进行。