Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/qt/6.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# 线程的异步RESTAPI调用会影响性能吗?_C#_Multithreading_Asynchronous - Fatal编程技术网

C# 线程的异步RESTAPI调用会影响性能吗?

C# 线程的异步RESTAPI调用会影响性能吗?,c#,multithreading,asynchronous,C#,Multithreading,Asynchronous,所以我的一个同事对我说- “为什么有人想用线程调用async RestAPIs,这是没有好处的,相反,它会为每个请求创建一个单独的线程。” 我的设想是—— public async Task<ApiResponse<ProductLookupDto>> GetProductsByValueOfTheDay() { string url = "http://domain.com?param=10120&isBasic=true" var result

所以我的一个同事对我说-

“为什么有人想用线程调用async RestAPIs,这是没有好处的,相反,它会为每个请求创建一个单独的线程。”

我的设想是——

public async Task<ApiResponse<ProductLookupDto>> GetProductsByValueOfTheDay()
{
    string url = "http://domain.com?param=10120&isBasic=true"
    var result = Task.Run(() => JsonConvert.DeserializeObject<ProductLookupDto>(SerializedResults.GET(url)));
    return new ApiResponse<ProductLookupDto>()
    {
        Data = await result,
        Message = "success"
    };
}
公共异步任务getProductsByValueOfDay()
{
字符串url=”http://domain.com?param=10120&isBasic=true"
var result=Task.Run(()=>JsonConvert.DeserializeObject(SerializedResults.GET(url));
返回新的ApiResponse()
{
数据=等待结果,
Message=“成功”
};
}
所以这里我使用异步线程。我知道它会为请求创建一个单独的线程。这是我对表现的关注

我想知道我的一些方法是否被一起调用,以及响应是否像我现在所做的那样是异步的。线程会影响性能吗?
请记住,来自rest调用的响应太大。

您的朋友实际上并不知道他在说什么-任务不会为每个请求创建单独的线程。相反,任务调度器将确定线程,标准使用线程池。这意味着线程是预先分配和重用的,特别是当您安排了大量任务时。由于完成端口的原因,请求运行时线程也会被释放。您的同事在这里严重缺乏基础知识。

我认为您的同事关注该代码是正确的,您可以说“它假装是异步的,但不是真正的”。Jon Skeet正确地指出,这里真正的问题在于
SerializedResults.GET
。不管它的具体实现是什么,它显然是一个阻塞调用,否则它将返回一个
任务
(可以是
等待
ed)而不是字符串。在
Task.Run中包装同步调用并将其称为异步调用是常见的错误。您根本没有消除阻塞,只是将阻塞调用移动到了另一个线程

因此,要使其异步,
SerializedResults.GET
需要执行。它应该被使用真正异步库的调用所取代,比如。由于这是一个JSON API(我有点偏颇),我将向您展示一个使用我的库的示例,它基本上是围绕HttpClient和JSON.NET的包装器,它提供了一些方便的方法来降低噪音:

public async Task<ApiResponse<ProductLookupDto>> GetProductsByValueOfTheDay()
{
    string url = "http://domain.com?param=10120&isBasic=true";
    var result = await url.GetJsonAsync<ProductLookupDto>();
    return new ApiResponse<ProductLookupDto>()
    {
        Data = result,
        Message = "success"
    };
}
公共异步任务getProductsByValueOfDay()
{
字符串url=”http://domain.com?param=10120&isBasic=true";
var result=await url.GetJsonAsync();
返回新的ApiResponse()
{
数据=结果,
Message=“成功”
};
}

线程和性能是两个正交的概念。线程不会使程序更快。如果目前可能的话,它们只允许您并行处理一些事情。这将为每个请求创建一个单独的任务-这将使用线程池。创建任务的开销相当小。也就是说,您应该阅读您理想情况下应该希望对
SerializedResuts.Get(…)
部分使用异步调用。您还不清楚“rest调用的响应太大”是什么意思。@JonSkeet,我从rest API得到的最终结果是大的。另外,不要试图学习成百上千的规定性绩效“规则”。编写清晰易读的代码来完成任务,同时为整个系统设定性能目标。然后测量性能。如果它达到了目标,那太好了,继续做下一份工作。如果没有,找出您的性能问题所在,并开始评估备选方案。不要只是尝试学习“始终执行X”或“从不执行Y”,因为很少有这样的绝对值。“在请求运行时,由于完成端口,线程也会被释放。”不在这里-有一个同步调用获取响应,因此将阻止线程执行该调用,直到它完成。这是这里的关键问题-为了有效地避免阻塞线程,OP确实需要异步发出web请求。@TomTom,多亏了你和Jon Skeet。据我所知,我做得不对。它假装是异步的,但实际上不是。它只会创建一个后台线程,然后重新使用它。我关心的不是阻止UI线程。你能帮我把它修改成异步的吗?或者:你实际上使用的是异步方法。我做了很多rest处理,相信我,实际上有一个异步API使rest请求完全异步。@TomTom,所以我的方法不会异步运行?例如,他们说使用
Task.Run
是一个坏主意。首先,您不调用异步方法,所以不会获得任何收益。运行不是一个坏主意——如果你需要并行处理,你需要线程。Async/await更适合于线程循环,但为此,您必须使用适当的异步API。你不知道。它们共存。我在交易平台上使用这两种方法。
…但是你通过将阻塞调用移动到后台线程来假装异步,这在大多数情况下没有什么好处这有什么好处?如果此代码来自Windows应用程序,则将阻止调用移动到后台线程会使UI线程保持响应。但是“真正的”异步在不消耗额外线程的情况下实现了同样的效果。这更可取。