我没有经常使用async / await,而且我对它们并不完全满意。我正在尝试进行异步运行同步操作。你能否告诉我以下代码片段是否有意义:
public static async Task<string> FileVersionAsync(string localFilePath)
{
FileVersionInfo versionInfo;
try
{
versionInfo = await Task.FromResult(FileVersionInfo.GetVersionInfo(localFilePath));
}
catch (SecurityException)
{
return "File Version Checker does not have permission to read file version";
}
catch (FileNotFoundException)
{
return "Unable to find configured file";
}
if (versionInfo.FileVersion == null)
return "N/A";
return versionInfo.FileVersion;
}
答案 0 :(得分:3)
添加Task
,await
和async
不会产生异步;他们只提供管道来处理异步代码发生时。在您的示例中:它永远不会异步发生,因此您所做的只是添加管道开销而没有任何好处。
编译器会生成 ton 的额外代码,结果永远不会被命中,因为当它到达await
时,它会发现任务已经完成完成,并将继续现有的线程。
实际上是异步的,你需要......异步的东西。这可能是外部IO,或者可能是与线程相关的东西 - 但请注意,只是跳转到另一个线程并不能为你买任何东西:它只是添加一个上下文切换。
如果有FileVersionInfo.GetVersionInfoAsync
方法,那么你所做的可能是值得的。
答案 1 :(得分:1)
不,没有意义。
使你的函数异步的唯一原因是它内部的某个地方等待其他异步函数。实际上,如果您忘记等待某个地方,您的编译器会发出警告。
async-await语法被发明为替代其他任务函数,如Task.ContinueWith,Task.FromResult,Task.FromException等。
In this interview Eric Lippert compared async-await with a cook who has to prepare breakfast在中间某处搜索async-await。
如果厨师必须准备断奶,他就开始煮水。但他没有等待水煮,而是开始切片面包,做其他事情。只有在他无事可做之后,他才开始无所事事地等待水煮沸,之后他就开始上茶。
类似地:如果程序必须等待外部进程执行请求(如数据库查询),将数据写入文件,从Internet等获取信息,async-await确保您的线程不会。等等。相反,您的线程会调高其调用堆栈,以查看其中一个调用者是否可以继续工作,而不会显示其他进程的结果。
您将在以下代码中看到这一点:
public async Task<string> ReadTextFile()
{
StreamReader txtReader = File.OpenText(...);
// read the complete text file; don't wait until finished yet
Task<String> taskTxt = txtReader.ReadToEndAsync();
// as we didn't use await, we can continue processing:
DoSomething();
// now we need the result from the read action: await for it
// the result of await Task<TResult> is the TResult:
string importedTxt = await taskTxt;
return importedTxt;
}
async-await的一些准则:
void
返回Task
,而不是TResult
返回Task<TResult>
await Task
的归还为void
; await Task<TResult>
的返回值为TResult
public async void Button_Clicked(object sender, EventArgs e)
{
// indicate you will do something time consuming:
this.ProgressBar1.Visible = true;
await DoSomethingTimeconsumingAsync(...);
// finished:
this.progressBar1.Visible = false;
}
这将确保无论何时线程必须等待某事,它都可以执行其他操作,因此您的GUI仍然可以响应。
答案 2 :(得分:0)
没有。似乎完全不需要使此方法异步,因为Task.FromResult已立即就绪。