2015-01-07 131 views
0

下面的代碼只是檢查圖像的URL,如果它是有效的。當我運行它如下,它檢查並立即返回異步等待永不結束,但立即同步運行

Function testUrl(ByVal myImage As String) As Boolean 

    myHttpClient.BaseAddress = New Uri(imageUrl) 
    myHttpResponse = myHttpClient.GetAsync(myImage).result 

    success= myHttpResponse.IsSuccessStatusCode 

End Function 

但是當我運行異步await,我不知道會發生什麼。因爲我在等待行上設置我的斷點並按f10,所以我沒有取得進展,我不確定是否因爲異步,它運行,但是如果我的斷點位於成功= myhttpresponse.issucessstatuscode,我不會在下一行看到任何中斷線。

Url是一個有效的url,第一個代碼立即返回true。我可以向任何人建議發生了什麼?

Async Function testUrl_async(ByVal myImage As String) As Task(Of Boolean) 

    myHttpClient.BaseAddress = New Uri(imageUrl) 
    myHttpResponse = Await myHttpClient.GetAsync(myImage) 

    success= myHttpResponse.IsSuccessStatusCode 

End Function 

編輯: 當我甚至嘗試下面的代碼,它沒有做任何事情。但是,如果沒有異步等待作品

Async Function testUrl_async() As Task(Of Boolean) 

     myHttpClient.BaseAddress = New Uri("http://www.logoeps.net/") 
       myImage = "wp-content/uploads/2013/06/stackoverflow_logo.jpg" 
     Try 
      myHttpResponse = Await myHttpClient.GetAsync(myImage) 

     Catch ex As Exception 

End Function 

     End Try 
+0

可能會有一些例外?添加try/catch來查看是否有異常發生,或者使用Visual Studio的「拋出異常時中斷」功能。你怎麼稱呼這個方法? –

+1

在調用testUrl_async()之後,應用程序的其餘部分是什麼樣的?您是否在異步調用有機會運行之前退出? – GazTheDestroyer

+0

@SriramSakthivel嘗試趕上沒有任何東西。顯然沒有例外 – batmaci

回答

2

聽起來好像你遇到了我在博客上描述的common deadlock issue。進一步調用堆棧,您可能需要致電Task.Wait()Task<T>.Result。這可能導致死鎖。

Await暫停其方法時,它首先捕獲一個「上下文」。這個「上下文」是SynchronizationContext.Current(除非它是null,在這種情況下它是TaskScheduler.Current)。如果您不熟悉SynchronizationContext,這只是表示如果在UI線程上運行,ASP.NET請求上下文(如果它在ASP.NET請求線程上運行)或線程池上下文中捕獲UI上下文(除非您'正在使用其他上下文)。此捕獲的上下文用於恢復方法Async

稍後,當等待完成時(在本例中爲HTTP Get),Async方法將嘗試恢復執行。但是,如果調用代碼被阻塞 UI線程/ ASP.NET請求線程,則該方法無法在該上下文中執行。因此上下文線程被阻塞,等待Async方法完成,並且Async方法被阻止,等待上下文空閒。僵局。

避免這種死鎖的最好方法是我在MSDN article on async best practices: 中描述的一路使用Async。換句話說,將Task.Wait()Task<T>.Result的呼叫替換爲Await

0

你的第一個例子工程,因爲訪問TaskResult當前線程,直到Result設置。幸運的是,看起來HttpClient.GetAsync()使用不同的線程(或更有可能的I/O完成端口)來完成它的工作,否則你的應用程序會死鎖。出於這個原因阻止異步方法通常是一個壞主意。

在第二個示例中更改爲await意味着當前線程將而不是塊的結果。相反,它會排隊設置結果時運行的其餘功能。此時將運行testUrl_async()調用後面的代碼。如果您在此時退出,排隊的testUrl_async()延續將永遠不會有機會運行。