C# 第二次调用HttpClient';s PostAsJsonAsync stucks
我试图将一些数据发布到web服务,并在控制台应用程序中使用HttpClient接收响应。如果我尝试重用HttpClient实例,那么对PostAsJsonAsync的第一个调用将按预期工作,但第二个调用将永远等待。如果我为每个调用创建一个新的HttpClient,那么一切都正常C# 第二次调用HttpClient';s PostAsJsonAsync stucks,c#,dotnet-httpclient,C#,Dotnet Httpclient,我试图将一些数据发布到web服务,并在控制台应用程序中使用HttpClient接收响应。如果我尝试重用HttpClient实例,那么对PostAsJsonAsync的第一个调用将按预期工作,但第二个调用将永远等待。如果我为每个调用创建一个新的HttpClient,那么一切都正常 public class DirectHandler { HttpClient httpClient; public string SendToPlayer(object message) {
public class DirectHandler
{
HttpClient httpClient;
public string SendToPlayer(object message)
{
if (httpClient == null)
{
httpClient = new HttpClient();
httpClient.BaseAddress = new Uri("..url...");
}
HttpResponseMessage response = httpClient.PostAsJsonAsync("", message).Result; // Blocking call!
if (response.IsSuccessStatusCode)
{
var result = response.Content.ReadAsByteArrayAsync().Result;
return System.Text.Encoding.Default.GetString(result);
}
else
{
throw new HttpRequestException("Error code " + response.StatusCode + ", reason: " + response.ReasonPhrase);
}
}
}
使用此类的代码:
DirectHandler dh = new DirectHandler();
var resp = dh.SendToPlayer(myObj);
Console.WriteLine("Received: " + resp);
Thread.Sleep(500);
resp = dh.SendToPlayer(myObj);
Console.WriteLine("Received: " + resp);
“服务器”是一个HttpListener:
public class HTTPServer
{
void StartListener()
{
HttpListener listener = new HttpListener();
listener.Prefixes.Add("my prefix");
listener.Start();
listener.BeginGetContext(new AsyncCallback(OnRequestReceive), listener);
}
private void OnRequestReceive(IAsyncResult result)
{
HttpListener listener = (HttpListener)result.AsyncState;
HttpListenerContext context = listener.EndGetContext(result);
HttpListenerResponse response = context.Response;
HttpListenerRequest request = context.Request;
using (var reader = new StreamReader(request.InputStream, request.ContentEncoding))
{
Console.WriteLine(reader.ReadToEnd());
}
string responseString = "{'a': \"b\"}";
byte[] buffer = Encoding.UTF8.GetBytes(responseString);
response.ContentLength64 = buffer.Length;
response.OutputStream.Write(buffer, 0, buffer.Length);
listener.BeginGetContext(new AsyncCallback(OnRequestReceive), listener);
}
}
如何重用HttpClient
更新:
我将.Result更改为async/await,现在SendToPlayer方法如下所示:
public async Task<string> SendToPlayer(object message)
{
if (httpClient == null)
{
httpClient = new HttpClient();
httpClient.BaseAddress = new Uri("..url...");
}
HttpResponseMessage response = await httpClient.PostAsJsonAsync("", message).ConfigureAwait(false);
if (response.IsSuccessStatusCode)
{
var result = await response.Content.ReadAsByteArrayAsync();
return System.Text.Encoding.Default.GetString(result);
}
else
{
throw new HttpRequestException("Error code " + response.StatusCode + ", reason: " + response.ReasonPhrase);
}
}
我不得不注意到,您提供的代码甚至都没有编译。比如主方法中的
myObj
来自哪里?既然方法StartListener
被声明为私有,那么您如何启动http侦听器呢?
这类问题使我怀疑您发布的代码不是具有所述问题的实际代码
另外,您在myObj中输入了什么内容
我复制并调整了你的代码,使它在我的机器上工作。请查看它是否在您的计算机上以及在新的控制台应用程序中运行(您需要管理员权限才能运行它)
现在,您可能已经简化了发布在此处的代码。如果有任何代码你没有张贴在这里,它将很难解决
您的HttpListener
是否在单独的(控制台)应用程序中运行?可能服务器进程在第一次调用后终止,例如由于错误
如果上述代码在新的控制台应用程序中有效,请尝试查找与代码的差异。在我看来,有两个问题: 1) 您的服务器需要等待处理多个事件,并且 2) 客户端和服务器代码应该驻留在单独的执行线程中 根据您编写的方式,服务器将在启动后不久关闭,这就是为什么第一个请求可以工作,但第二个请求挂起的原因 我创建了一个示例: 您必须首先启动服务器项目,它等待传入的请求(StartListening不会保持服务器线程打开,因此有一个while(IsRunning){thread.Sleep(100);}循环作为示例。 然后将客户端作为一个单独的进程启动,并观察它的控制台输出。它实际上会得到第二个响应(为什么会有5秒的延迟来让您看到这一点)。
希望这两个建议能有所帮助!当使用async/wait时,不要等待使用.Result或.wait()的异步方法,始终使用
wait
。根据上下文中的环境。Result和.wait可能会导致死锁。我将代码重写为使用wait而不是.Result,但没有任何更改。我还尝试了.postasjsync(…).ConfigureAwait(false),但对它的第二个调用仍然挂起。显示您如何重写代码,以便我们可以看到您所做的操作。使用该类的代码现在显示var resp=dh.SendToPlayer(myObj);
,这也应该等待:var resp=await dh.SendToPlayer(myObj);
。调用该代码段的方法也需要一直等待。如果单击“暂停”,调试器会在哪一行停止?您可能需要打开“线程”窗口切换到后台线程。同时给我们一个“任务”的屏幕截图Windows when paused.myObj是一个简单的DTO,但现在我也使用了一个整数。你的代码对我也适用。最初我的StartListener是公共的,可能在格式化过程中意外删除了它。我的DirectHandler与你的完全一样,也是主方法。服务器在第一次调用后不会停止(它在Unity3D应用程序中)(这里可能有什么?),StartListener在启动时调用),如果我重新启动客户端,它会再次响应第一个请求,但OnRequestReceive不会由第二个PostsJSONASync触发。正如我所说的,如果我在每次SendToPlayer调用中创建一个新的HttpClient,它就会工作。
public static void Main(string[] args)
{
Task.Run(async () =>
{
DirectHandler dh = new DirectHandler();
var resp = await dh.SendToPlayer(myObj);
Console.WriteLine("Received: " + str);
Thread.Sleep(500);
resp = await dh.SendToPlayer(myObj);
Console.WriteLine("Received: " + str);
}).Wait();
}
public static void Main(string[] args)
{
var s = new HTTPServer();
s.StartListener();
Task.Run(async () =>
{
var myObj = 8;
DirectHandler dh = new DirectHandler();
var resp = await dh.SendToPlayer(myObj);
Console.WriteLine("Received: " + resp);
Thread.Sleep(500);
resp = await dh.SendToPlayer(myObj);
Console.WriteLine("Received: " + resp);
}).Wait();
}
public class HTTPServer
{
public void StartListener()
{
HttpListener listener = new HttpListener();
listener.Prefixes.Add("http://*:8080/");
listener.Start();
listener.BeginGetContext(new AsyncCallback(OnRequestReceive), listener);
}
private void OnRequestReceive(IAsyncResult result)
{
HttpListener listener = (HttpListener)result.AsyncState;
HttpListenerContext context = listener.EndGetContext(result);
HttpListenerResponse response = context.Response;
HttpListenerRequest request = context.Request;
using (var reader = new StreamReader(request.InputStream, request.ContentEncoding))
{
Console.WriteLine(reader.ReadToEnd());
}
string responseString = "{'a': \"b\"}";
byte[] buffer = Encoding.UTF8.GetBytes(responseString);
response.ContentLength64 = buffer.Length;
response.OutputStream.Write(buffer, 0, buffer.Length);
listener.BeginGetContext(new AsyncCallback(OnRequestReceive), listener);
}
}
public class DirectHandler
{
HttpClient httpClient;
public async Task<string> SendToPlayer(object message)
{
if (httpClient == null)
{
httpClient = new HttpClient();
httpClient.BaseAddress = new Uri("http://localhost:8080");
}
HttpResponseMessage response = await httpClient.PostAsJsonAsync("", message).ConfigureAwait(false);
if (response.IsSuccessStatusCode)
{
var result = await response.Content.ReadAsByteArrayAsync();
return System.Text.Encoding.Default.GetString(result);
}
else
{
throw new HttpRequestException("Error code " + response.StatusCode + ", reason: " + response.ReasonPhrase);
}
}
}
8
Received: {'a': "b"}
8
Received: {'a': "b"}