C#中的以下代码序列是否有意义

时间:2018-01-05 14:18:23

标签: c# async-await

我没有经常使用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;
}

3 个答案:

答案 0 :(得分:3)

添加Taskawaitasync不会产生异步;他们只提供管道来处理异步代码发生时。在您的示例中:它永远不会异步发生,因此您所做的只是添加管道开销而没有任何好处。

编译器会生成 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的一些准则:

  • 如果至少调用一个其他异步函数
  • ,则仅使用async-await
  • 而不是void返回Task,而不是TResult返回Task<TResult>
  • 只有异常:异步事件处理程序:此异步函数返回void
  • 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已立即就绪。