Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/297.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# HttpClient.PostAsJsonAsync永远看不到帖子何时成功并响应_C#_Async Await_Dotnet Httpclient_Connection Timeout - Fatal编程技术网

C# HttpClient.PostAsJsonAsync永远看不到帖子何时成功并响应

C# HttpClient.PostAsJsonAsync永远看不到帖子何时成功并响应,c#,async-await,dotnet-httpclient,connection-timeout,C#,Async Await,Dotnet Httpclient,Connection Timeout,我们使用HttpClient将json发布到restful web服务。有一次,我们遇到了让我们困惑的事情。使用诸如postman、fiddler等工具,我们可以发布到端点并查看它是否工作。当我们对HttpClient.PostAsJsonAsync执行同样的操作时,我们可以在我们发布到的软件中验证它是否接收到了数据。然而,我们的postsjsonasync最终将超时,而不是给我们回复 我们已经与创建我们正在使用的服务的团队合作,并在我们这方面进行了额外的测试,但我们尚未能够真正暂停该服务 每次

我们使用HttpClient将json发布到restful web服务。有一次,我们遇到了让我们困惑的事情。使用诸如postman、fiddler等工具,我们可以发布到端点并查看它是否工作。当我们对HttpClient.PostAsJsonAsync执行同样的操作时,我们可以在我们发布到的软件中验证它是否接收到了数据。然而,我们的postsjsonasync最终将超时,而不是给我们回复

我们已经与创建我们正在使用的服务的团队合作,并在我们这方面进行了额外的测试,但我们尚未能够真正暂停该服务

每次我们使用HttpClient发布时,我们都可以验证我们发布到的目标软件是否确实获得了数据。每当我们从任何其他工具向目标软件发布帖子时,我们总是很快看到一个状态代码为200的响应。HttpClient无法接受来自此特定服务的响应。有人知道我们可以从这里看到什么吗

下面是代码(尽管它是如此的千篇一律,以至于我几乎感觉不需要它)


您不遵循异步等待模式有什么原因吗?您正在调用一个异步方法,但没有等待它。您没有说明调用REST服务的代码是Windows窗体还是ASP.NET应用程序,但
.Result

你能像这样重组你的方法吗

public async Task<string> PostData(string resourcePath, Object o, Boolean isCompleteUrl = false, int timeoutMinutes = -1)
{
    using (var client = new HttpClient())
    {
        if (timeoutMinutes > 0)
        {
            client.Timeout = new TimeSpan(0,timeoutMinutes,0);
        }
        var useUrl = isCompleteUrl ? resourcePath : ApiBase + resourcePath;
        var response = await client.PostAsJsonAsync(useUrl, o);
        if(response.StatusCode == System.Net.HttpStatusCode.OK)
        {
            return await response.Content.ReadAsStringAsync();
        }
        return "";
    }

}
public async Task PostData(字符串resourcePath,对象o,布尔值isCompleteUrl=false,int timeoutMinutes=-1)
{
使用(var client=new HttpClient())
{
如果(超时分钟数>0)
{
client.Timeout=newtimespan(0,timeoutMinutes,0);
}
var useUrl=isCompleteUrl?资源路径:ApiBase+resourcePath;
var response=wait client.postsjsonasync(useUrl,o);
if(response.StatusCode==System.Net.HttpStatusCode.OK)
{
return wait response.Content.ReadAsStringAsync();
}
返回“”;
}
}
这是:

var response = client.PostAsJsonAsync(useUrl, o).Result;
正在导致代码死锁。在异步API上阻塞时通常会出现这种情况,这就是为什么您会遇到“我看不到任何响应返回”的效果

这是如何造成僵局的?事实上,您正在包含同步上下文(可能属于UI)的环境中执行此请求。它正在执行异步请求,当响应到达时,它将通过一个IO完成线程继续,该线程尝试将继续发布到同一UI上下文中,该上下文当前被您的
.Result
调用阻止


如果要同步发出HTTP请求,请改用
WebClient
。如果您想正确地利用异步API,那么使用
等待
而不是
阻塞。Result

这是对@Justin Helgerson解决方案的一个轻微修改。方法中有2个阻塞
。Result
调用;一旦你开始异步,你应该修复它们

public async Task<string> PostDataAsync(string resourcePath, Object o, Boolean isCompleteUrl = false, int timeoutMinutes = -1)
{
    using (var client = new HttpClient())
    {
        if (timeoutMinutes > 0)
        {
            client.Timeout = new TimeSpan(0,timeoutMinutes,0);
        }
        var useUrl = isCompleteUrl ? resourcePath : ApiBase + resourcePath;
        var response = await client.PostAsJsonAsync(useUrl, o);
        if(response.StatusCode == System.Net.HttpStatusCode.OK)
        {
            return await response.Content.ReadAsStringAsync();
        }
        return "";
    }
}
public async Task PostDataAsync(字符串resourcePath,对象o,布尔值isCompleteUrl=false,int timeoutMinutes=-1)
{
使用(var client=new HttpClient())
{
如果(超时分钟数>0)
{
client.Timeout=newtimespan(0,timeoutMinutes,0);
}
var useUrl=isCompleteUrl?资源路径:ApiBase+resourcePath;
var response=wait client.postsjsonasync(useUrl,o);
if(response.StatusCode==System.Net.HttpStatusCode.OK)
{
return wait response.Content.ReadAsStringAsync();
}
返回“”;
}
}
注意,我还根据规范将该方法重命名为
PostDataAsync

在我们的例子中,这一行代码解决了这个问题。一个来自不同团队的开发人员提出了这个建议,而且它是有效的。我还没有在谷歌上搜索它,并充分阅读它,以解释这是在解决什么问题

我也遇到了同样的问题,并为自己解决了

简而言之,您必须使用
ConfigureAwait(false)
扩展来避免死锁:

var response = await client.PostAsJsonAsync(useUrl, o).ConfigureAwait(false);

谢谢你的回答。当我第一次研究web客户机与http客户机时,我读到http客户机是较新的,并且给人一种明显的印象,即web客户机将在未来被弃用。我还看到一些东西说,按照我的代码执行.Result是以阻塞方式使用HttpClient的一种可接受的方式。我将再看一看web客户端。谢谢。@Danny有时人们并不真正理解他们在错误地使用异步API。您也可以使用
HttpWebRequest
进行“原始”处理。Webclient也在做同样的事情。我认为可能是.net代码不喜欢我们正在使用的服务的测试/登台实例上的自签名证书。有一段时间在研究如何消除这种可能性,或者如果这是问题所在,就解决它。@Danny,甚至同步方法调用都会导致冻结?你试过胡乱提出这个要求吗?如果您删除SSC并使用
Http
,是否会发生这种情况?是的,我没有意识到我们正在通过代理(mulesoft API manager)访问服务。如果我们直接访问该服务,就可以让webclient正常工作。当我们反对api管理器代理时,我们被卡住了。因此,我们正在缩小我们的问题范围。感谢您抽出时间回答。在我的情况下,我希望它是一个同步调用。在web api服务器上调用时,此代码可以正常工作。我们还有第二个环境,在这个环境中,代码运行在我们称之为“任务服务器”的服务器上,该服务器本身就是一个运行在服务器上的服务,它接受一个排队的任务列表,并在其线程池中运行多个任务。在这种环境下,我们没有得到回应。所以我怀疑这是环境的不同。我可能会使用
System.Net.ServicePointManager.Expect100Continue = false;
var response = await client.PostAsJsonAsync(useUrl, o).ConfigureAwait(false);