簡體   English   中英

.NET 核心 ASP 控制器中的線程

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM