您可以同步调用异步 Web api 控制器方法吗?
假设我有一个具有以下 API 控制器方法的 Web 服务:
public async Task<ActionResult<string>> Get()
{
await Task.Delay(1000);
return Ok("Success");
}
看起来我可以像这样同步调用这个 api 控制器方法,
var url = "http://example.com/api/example";
var httpWebRequest = (HttpWebRequest)WebRequest.Create(url);
httpWebRequest.Method = "GET";
string webStringResult;
using (HttpWebResponse httpResponse = (HttpWebResponse)httpWebRequest.GetResponse())
{
using (var streamReader = new StreamReader(httpResponse.GetResponseStream()))
{
var result = streamReader.ReadToEnd();
webStringResult= JsonConvert.DeserializeObject<string>(result);
}
}
我对它的工作原理感到震惊。我认为我必须被迫使用 httpWebRequest.GetResponseAsync()
但似乎 httpWebRequest.GetResponse()
也有效。
我的问题是,这是否是正确的工作流程以及将 GetResponse()
与异步 Web 方法结合使用与 GetResponseAsync()
相比有何影响。通常,如果您直接从另一个库/类调用异步方法,则必须从异步方法调用它,并且必须等待它。但是,发出 Web 请求有点不同,因为从技术上讲您并不是直接调用该方法。所以我很惊讶地发现这有效,并且它将有助于了解这里发生的事情的含义/理解。
Let's say I have a webservice with the following API controller method:
public async Task<ActionResult<string>> Get()
{
await Task.Delay(1000);
return Ok("Success");
}
It seems like I can call this api controller method synchronously like such
var url = "http://example.com/api/example";
var httpWebRequest = (HttpWebRequest)WebRequest.Create(url);
httpWebRequest.Method = "GET";
string webStringResult;
using (HttpWebResponse httpResponse = (HttpWebResponse)httpWebRequest.GetResponse())
{
using (var streamReader = new StreamReader(httpResponse.GetResponseStream()))
{
var result = streamReader.ReadToEnd();
webStringResult= JsonConvert.DeserializeObject<string>(result);
}
}
I was shocked that this works. I thought that I would have to be forced to use httpWebRequest.GetResponseAsync()
But it seems like httpWebRequest.GetResponse()
also works.
My question is, if this is correct workflow and what the implications are of using GetResponse()
with an async web method versus GetResponseAsync()
. Normally if you're calling an async method directly from another library/class you must be calling it from an async method and you have to await it. However, making a web request is a little different since you're not technically directly calling the method. So I was surprised to see that this worked and it would help to know the implications/understanding of what is going on here.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
是的,在同一流程中。
正确的。客户端根本没有调用服务器方法。它正在向服务器发出 HTTP 请求。服务器应用程序通过调用服务器方法来处理该 HTTP 请求。
由于这些是不同的进程,因此服务器不关心客户端是同步还是异步;并且客户端并不关心服务器是同步还是异步。他们俩只是通过网络交谈。
GetResponse
只是意味着您的客户端是同步的。我想说,从技术上讲,它作为异步方法更合适,因为它是基于 I/O 的,但如果您对同步客户端感到满意,那就完全没问题。Yes, within the same process.
Right. The client isn't calling the server method at all. It's making an HTTP request to a server. The server application handles that HTTP request by invoking the server method.
Since these are different processes, the server doesn't care whether the client is synchronous or asynchronous; and the client doesn't care whether the server is synchronous or asynchronous. They're both just talking over the network.
GetResponse
just means your client is synchronous. I'd say it would technically be more proper as an asynchronous method, since it is I/O-based, but if you're fine with a synchronous client, then that's totally fine.一种思考方法是假设客户端和服务器是用不同的语言编写的,并且服务器代码是 20 年前编写的。它们可以一起工作,因为它们使用相同的协议(在本例中为 http),而不是因为它们是用相同版本的语言编写的。
话虽如此,请注意,即使您在同一台计算机上运行两者,甚至作为同一进程的一部分,这种通过使用 http 协议实现的分离也是正确的。例如,在测试中,您可以启动一个 Web 服务器并从同一个程序对其进行 http 调用(异步与否)。
另一种思考方式是想象客户端和服务器使用“文件协议':如果客户端想要完成工作,它将在一个特殊文件夹中放置一个带有 json 的文件;服务器监视此文件夹并读取文件,然后将响应保存为“response.json”。客户端可以使用
await File.WriteAllTextAsync
写入文件,服务器可以使用File.ReadAllText
(非异步)读取文件。One way to think about it is to assume that the client and the server are written in different languages and the server code was written 20 years ago. They can work together because they use the same protocol (http in this case) and not because they are written in the same version of a language.
Having said that, please note that this separation - achieved by using the http protocol - is true even if you running both on the same machine, and even as part of the same process. For example, in a test, you could start a web server and make http calls to it, async or not, from the same program.
Another way to think about it is to imagine that the client and server use a 'file protocol': if the client wants work done it drops a file with json in a special folder; the sever monitors this folder reads the file and later saves the response as 'response.json'. The client could write the file with
await File.WriteAllTextAsync
and the server could read the file withFile.ReadAllText
(not async).