1

为了监控我的 dotnet 核心应用程序,我使用 .NET clr profiling api 来获取方法级别的跟踪并计算任何方法完成其执行所花费的时间。我无法获得异步方法所花费的时间。

public ActionResult<IEnumerable<string>> Get()
    {
        Ok(RunQueryAsync().Result);
        return new string[] { "value1", "value2" };
    }
public async Task<String> RunQueryAsync()
    {
                // in the PostDataAsyncWithHeader I'm making async api request using HttpClient
                await PostDataAsyncWithHeader();
        }
        catch (Exception ex)
        {
            //display error message
            return "Exception: " + ex.Message;
        }
    }

在上面的代码中,我从 PostDataAsyncWithHeader() 方法发出 api 请求,这几乎需要 5 秒才能完成。但是当我使用 clr 分析 Enter 和 exit 挂钩来计算时间时,Get() 方法显示大约 5 秒,但 RunQueryAsync() 和 PostDataAsyncWithHeader() 方法显示 0ms。但实际时间由 PostDataAsyncWithHeader() 方法占用。

我想找到 PostDataAsyncWithHeader() 方法所花费的确切时间。请建议我如何实现它。

4

1 回答 1

3

clr 不了解异步方法,编译器将它们转换为常规方法和状态机。就运行时而言RunQueryAsync,这是一个简单的方法,它将创建状态机并调用它的MoveNext方法。这将运行异步方法的主体,直到第一个未同步完成的等待,然后它与Task对象一起返回。

Get另一方面,您的方法不是异步方法,当它调用Task<string>.Result它时会阻塞等待返回的任务RunQueryAsync完成。

确定异步方法何时完成可能意味着等待MoveNext状态机上的方法返回并检查状态机是否处于“完成”状态(我通常发现当状态为时状态机被认为是完成的-2,但我不希望这是合同)。

于 2021-06-04T03:00:11.427 回答