感谢书籍《ASP.NET Core 技术内幕与项目实战》及其作者杨中科。
“异步方法”:用async 关键字修饰的方法
- 异步方法的返回值一般是Task,T是真正的返回数据类型,如Task。惯例:异步方法名字以Async结尾。
- 如果方法无返回值,则应把返回值类型声明为Task。
- 调用泛型方法时,一般在方法前加上await,返回值就是泛型制定的T类型
- 一个方法如果有await调用,则这个方法也必须添加关键字async
```csharp
```csharp
```csharp
static void Main(string[] args)
{
string filename = "f:/1.txt";
File.Delete(filename);
File.WriteAllTextAsync(filename, "hello world");
string conttent =await File.ReadAllTextAsync(filename);
Console.WriteLine(conttent);
}
```csharp
提示编译错误如下:
Main函数声明添加async:
`
```csharp
``csharp
static async Task Main(string[] args)
{
string filename = "f:/1.txt";
File.Delete(filename);
File.WriteAllTextAsync(filename, "hello world");
string conttent =await File.ReadAllTextAsync(filename);
Console.WriteLine(conttent);
}
**疑问: File.WriteAllTextAsync(filename, "hello world"); 为什么不用await 也能成功执行?**
注意看下面的例子:
```csharp
string filename = "f:/1.txt";
File.Delete(filename);
StringBuilder strb = new StringBuilder();
for (int i = 0; i < 1000000; i++)
{
strb.Append(i.ToString());
}
File.WriteAllTextAsync(filename, strb.ToString());
Console.WriteLine(await File.ReadAllTextAsync(filename));
如上图,
Console.WriteLine(await File.ReadAllTextAsync(filename));
执行异常:
System.IO.IOException:“The process cannot access the file ‘f:\1.txt’ because it is being used by another process.”
提示 文件正在被其它进程操作。
猜想:可能是前面的File.WriteAllTextAsync(filename, strb.ToString());写入文件内容比较多,调用没有用await 修饰,所以程序没有等待File.WriteAllTextAsync(filename, strb.ToString());执行完毕,文件的句柄没有释放,就被 Console.WriteLine(await File.ReadAllTextAsync(filename));访问,所以打开了没有释放的文件句柄,就会提示错误。
验证如下File.WriteAllTextAsync(filename, strb.ToString()); 前加上await
string filename = "f:/1.txt";
File.Delete(filename);
StringBuilder strb = new StringBuilder();
for (int i = 0; i < 1000000; i++)
{
strb.Append(i.ToString());
}
await File.WriteAllTextAsync(filename, strb.ToString());
Console.WriteLine(await File.ReadAllTextAsync(filename));
```csharp
正常执行,且能正常输出内容。
**疑问2:一些系统定义的函数如winform 中的事件函数,调用了一步Async 方法,如何改变方法名称?**
wait() (无返回值) ; Result (有返回值) 。风险:死锁。
如下:
```csharp
static async Task<string> WriteFileAsync(int times,string filename)
{
File.Delete(filename);
StringBuilder strb = new StringBuilder();
for (int i = 0; i < times; i++)
{
strb.Append(i.ToString());
}
await File.WriteAllTextAsync(filename, strb.ToString());
String str =await File.ReadAllTextAsync(filename);
return str;
}
private void button1_Click(object sender, EventArgs e)
{
string filename = "f:/1.txt";
string length = WriteFileAsync(500, filename).Result;
MessageBox.Show(length.ToString());
}