1.异步方法与Task任务的区别
异步方法不同于Task任务,异步方法只是跳过当前方法去执行其它的语句,但仍然有可能阻塞其所在的线程。
2.举例说明:
private static async void taskTest()
{
await Task.Delay(100);
while (true)
{ }
}
此异步方法就会阻塞调用其方法所在的线程。比如将其放在Form的构造函数里就会阻塞主线程,卡住界面。
public Form1()
{
InitializeComponent();
Console.WriteLine(1);
taskTest();
Console.WriteLine(2);
}
该异步方法不会影响其后面的语句被执行,但会影响整个线程,1,2正常输出但该异步方法内是个死循环,Form的所在的主线程会卡住。
那为什么会出现这种情况呢,因为异步方法不同于Task创建一个新线程异步执行,异步方法里的同步代码放在最后执行,不会影响其他代码的执行,但仍然会阻塞主线程。
private static async void taskTest()
{
await Task.Delay(100);
Console.WriteLine("异步方法");
}
异步里面只写了一个输出语句,同时在Form1里面加个延时操作,结果先输出1,2,最后才输出异步方法里面的内容,证明异步方法内的输出在1,2后执行,并不是同时执行。具体来说就是,await Task.Delay(100)的代码执行完毕,主线程的未执行完,异步方法内剩余的代码将会等待主线程执行完再执行。
public Form1()
{
InitializeComponent();
Console.WriteLine(1);
taskTest();
Task.Delay(5000).Wait();
Console.WriteLine(2);
}
但将异步方法内的延迟改为同样的5秒,输出时间上不会发生变化,证明await Task.Delay(5000)是异步执行的。
3.结论:
异步方法和Task任务不同,并不会创建一个新的线程,而是放在其所在线程执行,await语句之外的代码其实是同步代码,会阻塞其所在的线程,拿上面的举例,只有await Task.Delay(100);在分线程中运行,是异步执行的,其余的代码都在主线程中运行。