30

.Net Framework 4.5 で実行されている ASP.Net MVC 4 Web Api プロジェクト内から HttpClient を使用して外部サービスを呼び出しています。

サンプル コードは次のとおりです (これは、外部サービスの呼び出しをテストするためのサンプル コードであるため、戻り値は無視してください)。

public class ValuesController : ApiController
{
    static string _address = "http://api.worldbank.org/countries?format=json";
    private string result;

    // GET api/values
    public IEnumerable<string> Get()
    {
        GetResponse();
        return new string[] { result, "value2" };
    }

    private async void GetResponse()
    {
        var client = new HttpClient();
        HttpResponseMessage response = await client.GetAsync(_address);
        response.EnsureSuccessStatusCode();
        result = await response.Content.ReadAsStringAsync();
    }
}

プライベート メソッドのコードは実際に機能しますが、私が抱えている問題は、コントローラーの Get() が GetResponse() を呼び出しますが、結果を待機せず、結果 = null で戻りをすぐに実行することです。

また、次のように WebClient を使用したより単純な同期呼び出しを使用してみました。

 // GET api/values
    public IEnumerable<string> Get()
    {
        //GetResponse();

        var client = new WebClient();

        result = client.DownloadString(_address);

        return new string[] { result, "value2" };
    }

これは正常に動作します。

私は何を間違っていますか?非同期サンプルで Get() がプライベート メソッドの完了を待機しないのはなぜですか?

4

2 に答える 2

40

ああ、私は次のことをする必要がありました (void ではなく Task を返します):

 // GET api/values
    public async Task<IEnumerable<string>> Get()
    {
        var result = await GetExternalResponse();

        return new string[] { result, "value2" };
    }

    private async Task<string> GetExternalResponse()
    {
        var client = new HttpClient();
        HttpResponseMessage response = await client.GetAsync(_address);
        response.EnsureSuccessStatusCode();
        var result = await response.Content.ReadAsStringAsync();
        return result;
    }

また、Get() 操作を非同期としてマークできることにも気づいていませんでした。これにより、外部呼び出しを待機できるようになりました。

Stephen Cleary のブログ投稿Async and Awaitに感謝し、正しい方向に導いてくれました。

于 2012-11-04T21:59:17.693 に答える