目录
异步方法不等于多线程:
异步方法的代码并不会自动在新线程中执行,除非把代码放到新线程中执行。
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相同
/*
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
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;
});
}
为什么有的异步方法没用async
async方法缺点:
- 异步方法会生成一个类,运行效率没有普通方法高
- 可能会占用非常多的线程
注意:
- 返回值为Task的不一定都要标注async,标注async只是让我们可以更方便的await
- 如果一个异步方法只是对别的异步方法调用的转发,并没有太多复杂的逻辑,那么就可以去掉async关键字
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.txt");
return s;
}
else if(num==2)
{
string s = await File.ReadAllTextAsync(@"e:\temp\b.txt");
return s;
}
}
//写法二,ReadAsync的返回值类型为Task<string>,不需要await
static Task<string> ReadAsync(int num)
{
if(num==1)
{
return File.ReadAllTextAsync(@"e:\a.txt");
}
else if(num==2)
{
return File.ReadAllTextAsync(@"e:\b.txt");
}
}
异步方法中尽量不要用Sleep方法:
如果想在异步方法中暂停一段时间,不要用Thread.Sleep(),因为它会阻塞调用线程,而要用await Task.Delay()
Thread.Sleep():同步延迟,会阻塞线程,不能取消
Task.Delay():异步延迟,不会阻塞线程,可以取消