HttpResponseMessage没有回复任何回复?

时间:2017-04-22 17:24:42

标签: c# asp.net-mvc api asynchronous

我尝试连接到API并从中获取数据。但是我没有在HttpResponseMessage代码行之后获得任何东西.if(response.IsSuccessStatusCode)永远不会运行。我已经尝试了一切,但还没有。请帮忙。这是我的代码。

using System;
using Newtonsoft;
using System.Net.Http.Headers; 
using System.Text; 
using System.Net.Http; 
using System.Web; 
using System.Collections.Generic;
using Newtonsoft.Json;
using System.Xml;
using System.Web.Mvc;
using System.Threading.Tasks;


namespace JKLLAppMobile.API
{
public class JKLLAPI : Controller
{
    public async Task<List<JasonData>> MakeRequest()
    {
        List<JasonData> HanaData = new List<JasonData>();

        var client = new HttpClient();
        var queryString = HttpUtility.ParseQueryString(string.Empty);
        queryString["format"] = "json";
        queryString["filter"] = "BDATU eq '20170421' and BWLVS eq '609'";
        var uri = "https://jkhapimdev.azure-api.net/api/beta/v2/bound/?" + queryString;

        HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, uri);
        request.Headers.Authorization = new AuthenticationHeaderValue("Ocp-Apim-Subscription-Key", "{Token-Key}");
        HttpResponseMessage response = await client.SendAsync(request);

        if (response.IsSuccessStatusCode)
        {
            var responseString = await response.Content.ReadAsStringAsync();
            string json_data = JsonConvert.SerializeObject(responseString); 


        }

        return HanaData;
    }
}

}

调用Ajax方法     函数TotalTestMonthly(){

    $.ajax({
        url: '../JKLLAPI/MakeRequest',
        type: 'POST',
        dataType: 'json',
        cache: false,
        async: false,
        data: {},
        success: function (data) { 
            if (data.Success == true) {

            } 
        }
    }); 
}

1 个答案:

答案 0 :(得分:2)

既然你已经说过“永远不会”运行IsSuccessStatusCode行,即使在超时后也没有,我猜你发生了死锁情况。

正如我上面评论的那样,Stephen Cleary有一个非常好的article来描述这个问题。他还写了MSDN article

总结(如果链接的文章消失了):

  • 当您进行异步调用时,当前的SynchronizationContext(或者,如果它为null,则为TaskScheduler)被捕获为异步调用的一种返回点。
  • GUI和ASP.NET应用程序使用SynchronizationContext。这只允许一个同步代码块一次运行。
  • 异步任务完成后,它将尝试返回SynchronizationContext,如果您从非异步位置开始,将在someTask.Wait();上阻止
  • 一旦达到这一点,就会出现同步代码正在等待异步代码的情况,并且异步代码正在等待返回同步代码,从而导致死锁。

注意:根据Stephen的MSDN文章,控制台应用程序没有此问题,因为它们使用TaskScheduler。 VS'单元测试任务运行器确实有这个问题,这就是我学习它的方法。

那么,你能做什么?

如果您正在从GUI上下文运行异步,例如单击按钮,您应该将按钮单击处理程序更改为异步方法:

// you can't change void to Task because of the type the delegate expects,
// but this is the correct way to do this.
public async void OnClicked(...)

然后您可以使用标准等待,并按照您的预期处理上下文。

在异步方法中,您可以调用ConfigureAwait:

await Task.Delay(1000).ConfigureAwait(continueOnCapturedContext: false);
// or, simply:
await Task.Delay(1000).ConfigureAwait(false);

这会导致该方法在线程池上下文中执行其余的异步方法,从而避免死锁。

如果由于某种原因你无法处理或包装异步方法,那么你也可以使用Task.Run

// You can also use Task<string>.Run(...), for example
var task = Task.Run(async () => await someAsyncMethod());
task.Wait();

使用Task.Run将在线程池上下文中执行异步方法,从而避免死锁。

我的解释实际上并没有正确的主题,所以我强烈建议阅读我上面链接的文章。我只是想确保我的答案包含一些有价值的内容,如果链接永远消失: - )

注意执行异步的正确方法是异步完全向下(即从按钮单击到最深的异步调用)。不应在异步方法中使用

我已经用我自己的快速示例来演示这些技巧:

// Deadlocks
public void button2_Click(object sender, EventArgs e)
{
    var task = GetNews();
    task.Wait();
    MessageBox.Show(task.Result);
}

// Doesn't deadlock
public async void button3_Click(object sender, EventArgs e)
{
    var result = await GetNews();
    MessageBox.Show(result);
}

// Doesn't deadlock
public void button4_Click(object sender, EventArgs e)
{
    var task = GetNews(false);
    task.Wait();
    MessageBox.Show(task.Result);
}

// Doesn't deadlock
public void button5_Click(object sender, EventArgs e)
{
    var task = Task<string>.Run(async () => await GetNews());
    task.Wait();
    MessageBox.Show(task.Result);
}

// The boolean option is just so that I don't have to write two example methods :)
// You obviously don't have to pass this as a parameter, and can just directly call ConfigureAwait
public async Task<string> GetNews(bool continueOnCapturedContext = true)
{
    await Task.Delay(100).ConfigureAwait(continueOnCapturedContext: continueOnCapturedContext);
    return "hello";
}