2016-09-20 142 views
1

我有一個簡單的方法,以異步格式工作,但當我嘗試將其更改爲同步格式時,它的行爲就像是死鎖,並且從不返回任何內容。我知道使用異步調用會更有效,但我很好奇爲什麼會發生這種情況。提前致謝。同步調用不工作,但異步

這將返回一個工作結果:

public static async Task getCompanyAsync(){ 
    var client = new getRestClient(); 
    var response = await companiesApi.GetCompaniesAsync(client); 
    var companies = response.GetResultAsync<List<Company>>(); 
} 

這將使程序坐和旋轉,直到我殺了它:

public static void getCompany(){ 
    var client = new getRestClient(); 
    var response = companiesApi.GetCompanies(client); 
    var companies = response.GetResult<List<Company>>(); 
} 

編輯:

因此,這裏是一些更詳細的代碼。

static void Main(string[] args) 
    { 
     MainAsync(args).Wait(); 
     Console.ReadLine(); 
    } 
    public static async Task MainAsync(string[] args) 
    { 
     await getCompanyAsync(); 
     getCompany(); 
    } 

    private static async Task getCompanyAsync() 
    { 
     var client = getApiClient(); 
     var companiesApi = new CompaniesApi(client); 
     var response = await companiesApi.GetCompaniesAsync(); 
     var companyies = await response.GetResultAsync<List<Company>>(); 
     foreach (var company in companyies) 
     { 
      Console.WriteLine(company.Name); 
     } 
    } 

    private static void getCompany() 
    { 
     var client = getApiClient(); 
     var companiesApi = new CompaniesApi(client); 
     var response = companiesApi.GetCompanies(); 
     var companyies = response.GetResult<List<Company>>(); 
     foreach (var company in companyies) 
     { 
      Console.WriteLine(company.Name); 
     } 

我應用程序運行如預期,當我提出getCompany();MainAsync()方法進Main()方法。

+1

這是你正在使用的任何庫的問題。您顯示的代碼不足以查看問題。 – Euphoric

+2

這是在UI還是控制檯應用程序中? (異步在不同環境中的工作方式可能有所不同)。順便提一句,第二個代碼片段甚至不應該編譯,因爲您在非異步方法中使用「await」。 – EJoshuaS

+0

@EJoshuaS在第二個片段中的等待是一個錯字,現在我已經編輯出來了。這在控制檯應用程序中運行。 – Bernie

回答

0

這裏有兩點。

首先,異步通常在控制檯應用程序中以意想不到的方式工作(與UI應用程序相比)。這是因爲UI具有「內置」同步上下文(顯然,因爲它們的「主」方法等效完成執行後不會自動退出),而控制檯應用程序則不會。請參閱this article瞭解如何在控制檯應用程序中使用上下文以緩解此問題。其次,正如斯蒂芬·克利裏在關於這個主題的優秀articles中指出的那樣,如果可以避免的話,阻止異步是一種不好的做法,因爲它可能會導致您描述的那種死鎖。基本上,解決這個問題的一種方法是使用異步「一路下來」 - 即在第二個示例中使用異步/等待而不是GetResult()。這個想法在異步最佳實踐的Microsoft documentation中得到了迴應,它建議您不要在第二個代碼示例中混合使用同步代碼和異步代碼。

在文章中,我鏈接到作者解釋了當混合同步代碼和異步代碼時如何發生死鎖。基本上,例如,當異步方法正在等待與GetResults()調用相同的上下文時,可能會發生這種情況。 (他的文章解釋說,雖然比我好很多:))。