2017-06-25 39 views
0

切中要害異步/等待和提琴手演示

爲什麼如果我嘗試在Visual Studio中運行下面的代碼,並且對「串urlContents =等待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"; 
     } 

更多的歷史和爲什麼我問上面

我的老闆的問題,我在討論異步/等待命令後,我讀:https://msdn.microsoft.com/library/hh191443(vs.110).aspx(這是我從上面得到的代碼)關於命令是如何工作的,我的老闆讓我做一些調查。他建議運行上面的代碼並對照Fiddler進行監控。當我這樣做時,我沒有得到我期望的結果。我希望調用msdn.microsoft.com後發生(任務getStringTask = client.GetStringAsync(「http://msdn.microsoft.com」);)。然而,它沒有發生

因此,我繼續研究命令。這促使我創建另一個演示。我建立了像上面那樣的新演示。然而,這個演示使用異步方法調用了數據庫,然後做了一些獨立的工作(就像上面一樣),然後使用await命令(就像上面一樣)。我使用SQL Profiler監視了這個演示。這個演示給了我我期望的結果。它向我證明了,在運行IndependentWork方法之前,異步命令會啓動數據庫調用。

這是以防萬一的代碼我沒有解釋清楚

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會啓動異步方法。我會在小提琴手中看到一個條目。處理將在獨立工作方法中繼續。然後在異步調用返回結果後繼續。這是第二個演示中發生的事情。

回答

0

我的猜測是,您觀察到的行爲是因爲調試器在請求發生之前停止執行應用程序。

當您在調試器中打斷點時,整個應用程序停止,它不會停止當前線程。如果您撥打的async方法在返回Task之前沒有提出請求,那麼您將無法在提琴手中看到它。

這可能也解釋了爲什麼你不用其他方法觀察它:它們在返回之前設法做出請求。