gpt4 book ai didi

c# - 如何用尽 ASP.NET 工作线程来显示异步等待模式的重要性

转载 作者:行者123 更新时间:2023-12-02 11:22:46 24 4
gpt4 key购买 nike

我试图用 async 向小学生展示异步编程的重要性。和 await .为此,我创建了一个带有一个 Controller 和两个 GET 操作的 ASP.NET Web API 项目。一个 GET 操作是同步的,另一个是异步的。

我想证明,在同步阻塞 i/o 调用的情况下,所有可用的 ASP.NET 工作线程都在等待并且没有做任何有用的事情,与此同时,当更多请求到达时,它们将超时,因为所有可用线程都在等待 I/O 线程完成。

问题是我下面的代码片段部分传达了这一点。它在异步调用的情况下按预期工作,但不适用于同步调用。如果我取消注释已注释掉的代码行,则不会发生这种情况,并且 ASP.NET 运行时可以处理更多线程。代码片段如下:

public class TestController : ApiController
{
// -> Uncommenting the below method proves my point of scalability <-
//public async Task<string> Get()
//{
// CodeHolder obj = new CodeHolder();
// return await obj.AsyncData();
//}
// -> Uncommenting the below method doesn't enforce time outs, rather waits <-
public string Get()
{
CodeHolder obj = new CodeHolder();
return obj.SyncData();
}
}
class CodeHolder
{
public string SyncData()
{
Task.Delay(10000).Wait();
return $"I am returned from Sync after waiting for 10 second at {DateTime.Now.ToString("HH:mm:ss:fffffff")}";
}
public async Task<string> AsyncData()
{
await System.Threading.Tasks.Task.Delay(10000);
return $"I am returned from Async after semi-waiting for 10 second at {DateTime.Now.ToString("HH:mm:ss:fffffff")}";
}
}

虽然我试图提出的这一点,随着同步调用需要很长时间才能完成,但我想知道为什么请求被保留在队列中而不是超时。我正在使用 JMeter 向我的 Web API 服务发送 250 个并发 HTTP 请求,但它们永远不会超时,而是一直等待并完成,尽管延迟非常大( ~250 秒 )。

顺便说一下,在异步版本中,所有响应都会在大约 10 秒内返回。

最佳答案

您可以证明同步版本使用线程池中的线程多于异步版本。
这就是我想出来的演示,web Controller :

[Route("api/v1/[controller]")]
public class ThreadController : Controller
{
private static readonly object locker = new object();

private static HashSet<int> syncIds = new HashSet<int>();

[HttpGet("sync")]
public ActionResult<string> GetSync()
{
var id = Thread.CurrentThread.ManagedThreadId;

lock (locker)
{
syncIds.Add(id);
}

Task.Delay(10000).Wait();

return $"I am returned from Sync after waiting for 10 second at {DateTime.Now.ToString("HH:mm:ss:fffffff")}";
}

[HttpGet("sync/count")]
public ActionResult<int> CountSync()
{
lock (locker)
{
int count = syncIds.Count;

syncIds.Clear();

return count;
}
}

private static HashSet<int> asyncIds = new HashSet<int>();

[HttpGet("async")]
public async Task<ActionResult<string>> GetAsync()
{
var id = Thread.CurrentThread.ManagedThreadId;

lock (locker)
{
asyncIds.Add(id);
}

await Task.Delay(10000);

return $"I am returned from Async after waiting for 10 second at {DateTime.Now.ToString("HH:mm:ss:fffffff")}";
}

[HttpGet("async/count")]
public ActionResult<int> CountAsync()
{
lock (locker)
{
int count = asyncIds.Count;

asyncIds.Clear();

return count;
}
}
}
一个模拟请求的控制台应用程序(我给了 150 毫秒的延迟,让一些时间到达等待块):
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;

namespace ConsoleApp
{
class Program
{
static void Main(string[] args)
{
using (var http = new HttpClient() )
{
var stopwatch = Stopwatch.StartNew();

var sync = new List<Task>();

for (int i = 0; i < 20; i++)
{
sync.Add(http.GetAsync("http://localhost:5000/api/v1/thread/sync") );

Thread.Sleep(150);
}

Task.WaitAll(sync.ToArray() );

stopwatch.Stop();

Console.WriteLine("Sync used " + http.GetAsync("http://localhost:5000/api/v1/thread/sync/count").Result.Content.ReadAsStringAsync().Result + " threads in " + stopwatch.ElapsedMilliseconds + "ms");

stopwatch.Restart();

var async = new List<Task>();

for (int i = 0; i < 20; i++)
{
async.Add(http.GetAsync("http://localhost:5000/api/v1/thread/async") );

Thread.Sleep(150);
}

Task.WaitAll(async.ToArray() );

stopwatch.Stop();

Console.WriteLine("Async used " + http.GetAsync("http://localhost:5000/api/v1/thread/async/count").Result.Content.ReadAsStringAsync().Result + " threads in " + stopwatch.ElapsedMilliseconds + "ms");
}

Console.ReadLine();
}
}
}
我得到的结果:
第一次运行:
Sync used 19 threads in 22412ms
Async used 8 threads in 12911ms
第二次运行:
Sync used 18 threads in 21083ms
Async used 10 threads in 12921ms
第三次运行:
Sync used 20 threads in 13578ms
Async used 10 threads in 12899ms
第四次运行:
Sync used 18 threads in 21018ms
Async used 5 threads in 12889ms

关于c# - 如何用尽 ASP.NET 工作线程来显示异步等待模式的重要性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52379267/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com