3

Я работаю над доказательством прототипа концепции.
У меня есть веб-форма Asp.Net C# (Visual Studio 2013, .Net 4.5). На кнопке мыши я сделать что-то вроде этого:Использование HttpClient.GetAsync для вызова Web API, похоже, зависает

List<Blog> blogs = null; 
protected void btnLoadData_Click(object sender, EventArgs e) 
{ 
    //...; 

    switch (int.Parse(rblDataSource.SelectedValue)) 
    { 
     //...; 

     case 4: 
      RunAsyncBlogs().Wait(); 

      break; 

     default: 
      blogs = localGetter.GetBlogs(); 
      break; 
    } 

    //...; 
} 

RunAsyncBlogs выглядит следующим образом:

static async Task RunAsyncBlogs() 
{ 
    using (var client = new HttpClient()) 
    { 
     client.BaseAddress = new Uri("http://localhost/wapiDemo/"); 
     client.DefaultRequestHeaders.Accept.Clear(); 
     client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json")); 

     // HTTP GET 
     HttpResponseMessage response = await client.GetAsync("api/Blogs"); 
     if (response.IsSuccessStatusCode) 
     { 
      List<Blog> thisBlogList = await response.Content.ReadAsAsync<List<Blog>>(); 
      var cnt = thisBlogList.Count(); 
     } 

    } 
} 

код останавливается в ответ = ждать client.GetAsync вызова. Когда я говорю, что он останавливается, отладчик действует так, как будто запрос завершен, но браузер все еще ждет.

Если я запускаю консольное приложение (копирую и вставляю в него метод RunAsync()), который вызывает Web API одинаково, я получаю свои данные. Итак, я считаю, что приложение веб-API отвечает так, как ожидалось.

ответ

3

Это:

RunAsyncBlogs().Wait(); 

ли запирание кода. Это синхронно блокирует вызов вашего метода асинхронного вызова, который пытается перевести продолжение на неявно захваченный контекст синхронизации. Вот почему вы shouldn't block on async code

protected async void btnLoadData_Click(object sender, EventArgs e) 
{ 
    // Other stuff 
    await RunAsyncBlogs(); 
} 
+0

@ Downvoter - Серьезно? Позаботьтесь о том, что случилось с ответом? –

0

Ваше событие нажатия кнопки должно быть асинхронной.

protected async void btnLoadData_Click(object sender, EventArgs e) 
{ 
    //...; 

    switch (int.Parse(rblDataSource.SelectedValue)) 
    { 
     //...; 

     case 4: 
      await RunAsyncBlogs(); 

      break; 

     default: 
      blogs = localGetter.GetBlogs(); 
      break; 
    } 

    //...; 
} 

Посмотрите это сообщение о проблемах с блокировкой при асинхронном режиме.

http://blog.stephencleary.com/2012/07/dont-block-on-async-code.html

1

Проблема заключается в том, что вы должны вложенными async методы. RunAsyncBlogs и response.Content.ReadAsAsync<List<Blog>>(); внутри него.

Добавление .ConfigureAwait(false) в конце следующей строки предотвратит ваш код от подвешивания:

var thisBlogList = await response.Content.ReadAsAsync<List<Blog>>().ConfigureAwait(false); 

Однако, несмотря на то, что это решит блокировки, код будет выполняться синхронно, из-за Wait() вызова в btnLoadData_Click метода.

Переключение на асинхронное выполнение, как уже было предложено, является лучшим решением.

+0

Это сработало для меня, спасибо! –

0

это веб-приложение с VS2013 с WebAPI и MVC В MVC У меня есть я связываю с этим:

public JsonResult GetWithHttpClient() 
{ 

Employee employee = null; 
using (var client = new HttpClient()) 
{ 

    client.BaseAddress = new Uri(path); 
    client.DefaultRequestHeaders.Accept.Clear(); 
    client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json")); 

    HttpResponseMessage response = client.GetAsync("api/Employees/12345").Result; 

    //the IsSuccessStatusCode property is false if the status is an error code. 
    //All the error: {StatusCode: 401, ReasonPhrase: 'Unauthorized', Version: 1.1, Content: System.Net.Http.StreamContent, Headers:{ Pragma: no-cache X-SourceFiles: =?UTF-8?B?QzpcRkFCSU9fQ09ESUNFXE15RXhhbXBsZVxXZWJBcHBsaWNhdGlvbjFcV2ViQXBwbGljYXRpb24xXGFwaVxFbXBsb3llZXNcMTIzNDU=?= Cache-Control: no-cache Date: Tue, 28 Jul 2015 14:47:03 GMT Server: Microsoft-IIS/8.0 WWW-Authenticate: Bearer X-AspNet-Version: 4.0.30319 X-Powered-By: ASP.NET Content-Length: 61 Content-Type: application/json; charset=utf-8 Expires: -1}} 
     if (response.IsSuccessStatusCode) 
     { 
      employee = response.Content.ReadAsAsync<Employee>().Result;    

    } 
} 

return Json (employee, JsonRequestBehavior.AllowGet); 

}

WebAPI называется EmployeesController. И у меня есть этот метод:

public Employee Get(int id) 
{ 
return list.First(e => e.Id == id); 
} 
Смежные вопросы