原理
其实不管是Task,ThreadPool,本质最终都是Thread。只不过微软帮我们在简化线程控制的复杂度。
线程池是CLR中事先定义好的一些线程。Task取的线程池,只不过在语法上,可以非常方便取返回值。
异步会提高程序的运行速度吗
多线程会提高程序的效率,不会提高运行速度。
这就好比这一个任务让前台花1个小时。前台完成10分钟的时候
打电话给经理,让他安排一个人来干30分钟(new Thread()),他干剩下的20分钟。(创建线程,需要时间,内存资源)
或者从旁边空闲的同事中(ThreadPool 或 Task),拉一个人过来干30分钟。他干剩下的20分钟。(需要的时间少,资源本来就存在)
从上看出,异步会让一份任务时间变长。资源消耗更多。但是可以让前台(UI线程)空闲下来,听从领导(用户)指挥。
async和await只是一个标记
Task的用法1:
初始化: Task tack = new Task(委托方法); //委托方法也可以是lambda表达式或者匿名函数
异步执行委托的方法: task.start();
Task的用法2:
直接调用Task封装的静态方法Run: Task.Run(委托方法);//这样在定义玩之后会开一个新线程直接执行委托的方法
注意:系统要执行Task的委托函数时,会开一个新的线程去执行,主线程继续执行下面的代码
async/await用法:
主线程碰到await后会立刻返回,以非阻塞的形式执行后面的代码。
在Task对象前面用 await会阻塞线程,直到Task中的异步操作结束,并返回结果。程序才会继续执行。
首先看个Demo,
static void Main(string[] args)
{
Task.Run(() => //异步开始执行
{
Thread.Sleep(1000); //异步执行一些任务
Console.WriteLine("Hello World"); //异步执行完成标记
});
Thread.Sleep(1100); //主线程在执行一些任务
Console.WriteLine("Main Thread"); //主线程完成标记
Console.ReadLine();
}
1.凡是使用await关键字的方法,都必须打上async标记。
2.async表示方法内有异步方法,调用async方法,会立刻另起线程执行。
3.await表示等待异步方法执行完,并取返回值。
await 仅在当前方法中有效,如果await 不在主线程中使用,那么并不能阻塞当前线程继续执行主线程
实例1:
static void Main(string[] args)
{
Console.WriteLine("A"+Thread.CurrentThread.ManagedThreadId);
Task<string> t = callAsya("AAA");
Console.WriteLine(t.Result);
Task<string> t1 = callAsyb("AAA");
Console.WriteLine(t1.Result);
//分别执行callAsya与callAsyb,输出顺序相同
Console.WriteLine("B" + Thread.CurrentThread.ManagedThreadId);
Console.Read();
}
private static Task<string> callAsya(string name)
{
return Task.Run<string>(() => //没有await
{
Thread.Sleep(1000);
return $"Name:{name},{Thread.CurrentThread.ManagedThreadId}";
});
}
private static async Task<string> callAsyb(string name)
{
return await Task.Run<string>(() => //增加await
{
Thread.Sleep(1000);
return $"Name:{name},{Thread.CurrentThread.ManagedThreadId}";
});
}
输出结果为:
A10
Name:AAA,11
B10
实例2:
static void Main(string[] args)
{
Console.WriteLine("A"+Thread.CurrentThread.ManagedThreadId);
Task<string> t = callAsya("AAA");
t.ContinueWith(t1 =>
{
string result = t1.Result;
Console.WriteLine(result);
});
//主线程中使用阻塞,调用callAsya("AAA")与callAsyb("AAA"),返回结果相同
Console.WriteLine("B" + Thread.CurrentThread.ManagedThreadId);
Console.Read();
}
private static Task<string> callAsya(string name)
{
return Task.Run<string>(() =>
{
Thread.Sleep(1000);
return $"Name:{name},{Thread.CurrentThread.ManagedThreadId}";
});
}
private static async Task<string> callAsyb(string name)
{
return await Task.Run<string>(() => //增加await
{
Thread.Sleep(1000);
return $"Name:{name},{Thread.CurrentThread.ManagedThreadId}";
});
}
输出结果为:
A9
B9
Name:AAA,10