一.异步方法不等于多线程,异步方法的代码并不会自动在新线程中执行除非手动将代码放到新线程中
static async Task Main(string[] args)
{
Console.WriteLine("调用之前:"+Thread.CurrentThread.ManagedThreadId);
double r=await CalcAsync(5000);
Console.WriteLine($"r{r}");
Console.WriteLine("调用之后:"+Thread.CurrentThread.ManagedThreadId);
}
public static async Task<double> CalcAsync(int n)
{
//下面这段代码输出的线程ID调用前和调用后的线程ID是一致的
/*
Console.WriteLine("CalcAsync,"+Thread.CurrentThread.ManagedThreadId);
double result=0;
Random=new Random();
for(int i=0;i<n;i++)
{
result=rand.NextDouble();
}
return result ;*/
//下面这段代码输出的线程ID,调用前和调用后的线程ID不一致,输出的是新线程ID
return await task.Run(()=>
{
Console.WriteLine("CalcAsync,"+Thread.CurrentThread.ManagedThreadId);
double result=0;
Random rand=new Random();
for(int i=0;i<n*n;i++)
{
result+=rand.NextDouble();
}
return result;
});
}
//下面是直接将Task运行完成之后的结果封装到Task里面,而没有await
public static Task<double> Calc2Async(int n)
{
return Task.Run(()=>{
Console.WriteLine("CalcAsync,"+Thread.CurrentThread.ManagedThreadId);
double result=0;
Random rand=new Random();
for(int i=0;i<n*n;i++)
{
result=result+rand.NextDouble();
}
return Task.FromResult(result);
})
}
二.为什么有的异步没有用async修饰
async方法的缺点:1.异步方法会生成一个类,运行效率没有普通方法高 2.可能会占用非常多的线程
标明async只是为了更方便的使用await,第二种没有使用async,如果需要将Task的结果拿出来进行操作的时候
需要使用async和await
static async Task Main(string[] args)
{
string s=await ReadAsync(1);
Console.WriteLine(s);
}
//第一种写法
static async Task<string> ReadAsync(int num)
{
if(num==1)
{
string s=await File.ReadAllTextAsync(@"e:\temp\a\1.txt");
return s;
}
else if(num==2)
{
string s=await File.ReadAllTextAsync(@"e:\temp\a\2.txt");
return s;
}
}
//第二种写法,这种写法效率高,ReadAsync的返回值类型为Task<string>
static Task<string> ReadAsync(int num)
{
if(num==1)
{
return File.ReadAllTextAsync(@"e:\a\1.txt");
}
else if(num==2)
{
return File.ReadAllTextAsync(@"e:\a\2.txt");
}
}
三 .为什么尽量少使用Thread.Sleep();
Thread.Sleep(3000)与await Task.Delay(3000)的区别
Thread.Sleep():终止的是当前线程,会降低并发(类似于接线员停止了)
await Task.Delay():是编译后的MoveNext中延时(我们打10086停止说话,但是接线员可以去接别人的电话)