async / await和Fiddler Demo

时间:2017-06-25 19:35:53

标签: c# async-await

通往点的权利

为什么我尝试在Visual Studio中运行下面的代码,并在“字符串urlContents = await getStringTask; ”行中有一个断点,我没有看到对msdn的调用.microsoft.com直到我执行该行。

我希望在处理执行行之后调用msdn.microsoft.com:任务getStringTask = client.GetStringAsync(“http://msdn.microsoft.com”);

这是异步方法的重点,对吗?启动可能需要一段时间才能运行的任务(client.GetStringAsync),这样独立工作(DoIndependentWork();)可以在较长任务执行时继续工作。

我对结果感到困惑。有人可以解释为什么会这样。

我在想这是因为我正在开发机器上运行所有内容。

public partial class MainWindow : Window
    {
        // Mark the event handler with async so you can use await in it.
        private async void StartButton_Click(object sender, RoutedEventArgs e)
        {

            int contentLength = await AccessTheWebAsync();

            resultsTextBox.Text +=
                String.Format("\r\nLength of the downloaded string: {0}.\r\n", contentLength);
        }


        // Three things to note in the signature:
        //  - The method has an async modifier. 
        //  - The return type is Task or Task<T>. (See "Return Types" section.)
        //    Here, it is Task<int> because the return statement returns an integer.
        //  - The method name ends in "Async."
        async Task<int> AccessTheWebAsync()
        {
            // You need to add a reference to System.Net.Http to declare client.
            HttpClient client = new HttpClient();

            // GetStringAsync returns a Task<string>. That means that when you await the
            // task you'll get a string (urlContents).
            Task<string> getStringTask = client.GetStringAsync("http://msdn.microsoft.com");

            // You can do work here that doesn't rely on the string from GetStringAsync.
            DoIndependentWork();

            // The await operator suspends AccessTheWebAsync.
            //  - AccessTheWebAsync can't continue until getStringTask is complete.
            //  - Meanwhile, control returns to the caller of AccessTheWebAsync.
            //  - Control resumes here when getStringTask is complete. 
            //  - The await operator then retrieves the string result from getStringTask.
            string urlContents = await getStringTask;

            // The return statement specifies an integer result.
            // Any methods that are awaiting AccessTheWebAsync retrieve the length value.
            return urlContents.Length;
        }

        void DoIndependentWork()
        {
            resultsTextBox.Text += "Working . . . . . . .\r\n";
        }

更多历史记录以及我为什么要问上述问题

我的老板和我在阅读之后讨论了async / await命令:https://msdn.microsoft.com/library/hh191443(vs.110).aspx(这是我从上面得到代码的地方。)关于这些命令如何工作有一些争论,所以我的老板让我去做一些调查。他建议运行上面的代码并对Fiddler进行监控。当我这样做时,我没有得到我预期的结果。我原以为msdn.microsoft.com的调用是在行之后发生的(任务getStringTask = client.GetStringAsync(“http://msdn.microsoft.com”);)。但是,它没有发生

所以,我继续研究这些命令。这促使我创建另一个演示。我像上面那样设置了新的演示。但是,这个演示使用异步方法调用数据库,然后做了一些独立的工作(就像上面一样),然后使用await命令(就像上面一样)。我使用SQL Profiler监控了这个演示。这个演示给了我预期的结果。事实证明,在运行IndependentWork方法之前,async命令会启动数据库调用。

这是代码,以防万一我没有清楚解释

public class HomeController : Controller
{
    public Task<string> Index()
    {
        var returnValue = MacroService();

        return returnValue;
    }

    public async Task<string> MacroService()
    {
        Task<string> getStringTask = MicroDataService("MicroDataServiceCall");

        string string2 = IndependentWork("IndependentWorkCall");

        string stringTask1 = await getStringTask;

        return $"{stringTask1}, {string2}";
    }

    public async Task<string> MicroDataService(string parm)
    {
        string connectionString = ConfigurationManager.ConnectionStrings["xzz"].ConnectionString;

        var conn = new SqlConnection(connectionString);

        var command = new SqlCommand("sproc", conn);
        command.CommandType = CommandType.StoredProcedure;

        SqlParameter param = new SqlParameter("@ID", SqlDbType.VarChar);
        param.Direction = ParameterDirection.Input;
        param.Value = "00000";
        command.Parameters.Add(param);

        conn.Open();
        await command.ExecuteNonQueryAsync();
        conn.Close();

        return parm;
    }

    public string IndependentWork(string parm)
    {
        return parm;
    }

所以,我想知道为什么我从原始演示中得不到相同的结果,因为我知道我的老板会问。

我在想这是因为我正在我的开发机器上运行第一个演示的所有内容。在第二个演示中,我实际上使用的是数据库服务器,因此第二个演示开始了该机器上的数据库处理。

让我知道。感谢!!!

很抱歉,如果我的描述/期望不明确。让我试着更清楚。

我对第一个演示的预期结果是,在任务getStringTask = client.GetStringAsync(“http://msdn.microsoft.com”)之后,我会在Fiddler中看到http://msdn.microsoft.com的调用。执行。但是,直到行字符串urlContents = await getStringTask之后,才在Fiddler中看到调用;执行。

因此,第一个演示没有给出我预期的结果。

但是,第二个演示给了我预期的结果。这是我在SQL Profiler中看到对数据库的调用之后的行:Task getStringTask = MicroDataService(“MicroDataServiceCall”);执行。

所以,我试图理解为什么我有不同的行为。我原以为demo1会启动异步方法。我会在Fiddler看到一个条目。处理将在IndependentWork方法中继续进行。然后从异步调用返回结果后继续。这是第二个演示中发生的事情。

1 个答案:

答案 0 :(得分:0)

我的猜测是你观察到的行为是因为调试器在发出请求之前就停止了应用程序的执行。

当您在调试器中遇到断点时,整个应用程序停止,它不会仅停止当前线程。如果你调用的async方法在返回Task之前没有提出请求,那么你就不会在Fiddler中看到它。

这也可能解释了为什么你没有用其他方法观察到这一点:他们确实设法在返回之前提出请求。