[英]Threading in .NET core ASP Controllers
我已經創建了 .net Core 3.0 Web 應用程序的干凈項目,我試圖了解ThreadPool
在 C# 中的工作原理。
namespace TestASPSelf.Controllers
{
public class HomeController : Controller
{
private readonly ILogger<HomeController> _logger;
public static int countThread = 0;
public HomeController(ILogger<HomeController> logger)
{
_logger = logger;
}
public IActionResult Index()
{
int workerThreads;
int portThreads;
ThreadPool.GetMaxThreads(out workerThreads, out portThreads);
Console.WriteLine("\nMaximum worker threads: \t{0}" +
"\nMaximum completion port threads: {1}",
workerThreads, portThreads);
ThreadPool.GetAvailableThreads(out workerThreads,
out portThreads);
Console.WriteLine("\nAvailable worker threads: \t{0}" +
"\nAvailable completion port threads: {1}\n",
workerThreads, portThreads);
Console.WriteLine("countThread = " + countThread);
return View();
}
class Z
{
public static void WaitTest(object o)
{
countThread++;
while (true)
{
Thread.Sleep(1000);
}
}
}
public IActionResult Privacy()
{
for (int i = 0; i < 100; i++)
{
Console.WriteLine("starting thread "+i);
ThreadPool.QueueUserWorkItem(new WaitCallback(Z.WaitTest));
}
return View();
}
}
}
當http://localhost:5000/Home/Privacy打開時,它會掛起一段時間(大約 40-80 秒),但我看到,其中for
循環邏輯幾乎立即完成。 當http://localhost:5000/之后打開時,它也會掛起 40-80 秒,結果是控制台countThread = 100
。 啟動線程時,應用程序的 CPU 使用率約為 5-10%。
我試圖理解:
1)第一個是為什么 ASP controller 每頁掛起 40-80 秒,當 100 個線程正在運行時,CPU 使用率為 5-10%。 CPU有很多資源,RAM也是空閑的,但是為什么頁面的ASP Controller方法掛了?
2) 如何在 C# 中創建線程池,運行線程數有限? 如果我理解方法public static bool SetMinThreads (int workerThreads, int completionPortThreads);
正確地,它會影響應用程序的所有線程。 如何在活動線程數有限的情況下創建 ThreadPool 的 object,例如 Java 中的ExecutorService
? 例如,線程池的 Java 代碼可能如下所示
ExecutorService executor = Executors.newFixedThreadPool(5);
for (int i = 0; i < 10; i++) {
Runnable worker = new WorkerThread("" + i);
executor.execute(worker);
}
executor.shutdown();
while (!executor.isTerminated()) {
}
3) 如何防止 ASP Controller 的所有方法掛起並制作“真正的”線程,如 Java 中的線程?
ThreadPool.QueueUserWorkItem(new WaitCallback(Z.WaitTest));
有了這個,你會做一些非常錯誤的事情。 您導致線程池中的線程阻塞,因此池無法完成處理您的請求並處理新請求。
在某個時候,池中的一個線程設法返回並處理您的下一個請求,但由於池過載,它再次掛起。
至於您的其他問題,請說明您想要實現的目標。 您的問題似乎試圖解決一個不太了解的問題。
更新:在亞瑟的評論之后。
如果你要下載文件,你應該使用 Tasks 和 async-await。 IO 操作不消耗線程(更多 在這里)。
創建N個任務,每個下載一個文件,然后等待Task.WhenAll。 偽代碼:
List<Task> tasks = new List<Task>();
for (int i = 0; i < filesToDownloadCount; i++)
{
var t = new Task ( () => { /* ... code to download your file here ... */});
tasks.Add (t);
}
await t.WhenAll (tasks);
這種方法將為您提供最佳吞吐量,您的瓶頸將是您的帶寬,而不是 CPU。
ThreadPool class 有幾個 static 方法,包括負責在線程池工作線程可用時調用線程池工作線程的 QueueUserWorkItem。 如果線程池中沒有可用的工作線程,它會一直等到線程可用。
using System;
using System.Threading;
class ThreadPoolSample
{
// Background task
static void BackgroundTask(Object stateInfo)
{
Console.WriteLine("Hello! I'm a worker from ThreadPool");
Thread.Sleep(1000);
}
static void BackgroundTaskWithObject(Object stateInfo)
{
Person data = (Person)stateInfo;
Console.WriteLine($"Hi {data.Name} from ThreadPool.");
Thread.Sleep(1000);
}
static void Main(string[] args)
{
// Use ThreadPool for a worker thread
ThreadPool.QueueUserWorkItem(BackgroundTask);
Console.WriteLine("Main thread does some work, then sleeps.");
Thread.Sleep(500);
// Create an object and pass it to ThreadPool worker thread
Person p = new Person("Mahesh Chand", 40, "Male");
ThreadPool.QueueUserWorkItem(BackgroundTaskWithObject, p);
int workers, ports;
// Get maximum number of threads
ThreadPool.GetMaxThreads(out workers, out ports);
Console.WriteLine($"Maximum worker threads: {workers} ");
Console.WriteLine($"Maximum completion port threads: {ports}");
// Get available threads
ThreadPool.GetAvailableThreads(out workers, out ports);
Console.WriteLine($"Availalbe worker threads: {workers} ");
Console.WriteLine($"Available completion port threads: {ports}");
// Set minimum threads
int minWorker, minIOC;
ThreadPool.GetMinThreads(out minWorker, out minIOC);
ThreadPool.SetMinThreads(4, minIOC);
// Get total number of processes availalbe on the machine
int processCount = Environment.ProcessorCount;
Console.WriteLine($"No. of processes available on the system: {processCount}");
// Get minimum number of threads
ThreadPool.GetMinThreads(out workers, out ports);
Console.WriteLine($"Minimum worker threads: {workers} ");
Console.WriteLine($"Minimum completion port threads: {ports}");
Console.ReadKey();
}
// Create a Person class
public class Person
{
public string Name { get; set; }
public int Age { get; set; }
public string Sex { get; set; }
public Person(string name, int age, string sex)
{
this.Name = name;
this.Age = age;
this.Sex = sex;
}
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.