Udostępnij przez


Zarządzana przez system pula wątków

Klasa System.Threading.ThreadPool udostępnia aplikacji pulę wątków roboczych zarządzanych przez system, co pozwala skoncentrować się na zadaniach aplikacji, a nie na zarządzaniu wątkami. Jeśli masz krótkie zadania wymagające przetwarzania w tle, zarządzana pula wątków jest łatwym sposobem korzystania z wielu wątków. Korzystanie z puli wątków jest znacznie łatwiejsze w Framework 4 lub nowszym, ponieważ można tworzyć obiekty Task i Task<TResult>, które wykonują zadania asynchroniczne w puli wątków.

Platforma .NET używa wątków puli wątków do wielu celów, w tym operacji biblioteki równoległej zadań (TPL ), asynchronicznego uzupełniania we/wy, wywołań zwrotnych czasomierza , zarejestrowanych operacji oczekiwania, asynchronicznych wywołań metod przy użyciu delegatów i System.Net połączeń gniazd.

Cechy puli wątków

Wątki puli wątków to wątki w tle . Każdy wątek używa domyślnego rozmiaru stosu, działa z domyślnym priorytetem i znajduje się w wielo wątkowym apartamencie. Gdy wątek w puli wątków zakończy zadanie, zostanie on zwrócony do kolejki oczekujących wątków. Od tego momentu można go ponownie użyć. Ponowne użycie umożliwia aplikacjom uniknięcie kosztów tworzenia nowego wątku dla każdego zadania.

Istnieje tylko jedna pula wątków na proces.

Wyjątki w wątkach puli wątków

Nieobsługiwane wyjątki w wątkach puli wątków kończą proces. Istnieją trzy wyjątki od tej reguły:

Aby uzyskać więcej informacji, zobacz Wyjątki w zarządzanych wątkach.

Maksymalna liczba wątków puli wątków

Liczba operacji, które można zakolejkować w puli wątków, jest ograniczona jedynie przez dostępną pamięć. Jednak pula wątków ogranicza liczbę wątków, które mogą być aktywne w procesie jednocześnie. Jeśli wszystkie wątki puli wątków są zajęte, dodatkowe elementy robocze są kolejkowane do momentu udostępnienia wątków do ich wykonania. Domyślny rozmiar puli wątków dla procesu zależy od kilku czynników, takich jak rozmiar wirtualnej przestrzeni adresowej. Proces może wywołać metodę ThreadPool.GetMaxThreads w celu określenia liczby wątków.

Maksymalną liczbę wątków można kontrolować przy użyciu metod ThreadPool.GetMaxThreads i ThreadPool.SetMaxThreads.

Uwaga / Notatka

Kod hostujący środowisko uruchomieniowe języka wspólnego może ustawić rozmiar przy użyciu ICorThreadpool::CorSetMaxThreads metody .

Minimalna liczba wątków w puli

Pula wątków udostępnia nowe wątki robocze lub wątki zakończenia operacji wejścia/wyjścia na żądanie, dopóki nie osiągnie określonego minimum dla każdej kategorii. Możesz użyć ThreadPool.GetMinThreads metody , aby uzyskać te minimalne wartości.

Uwaga / Notatka

Gdy zapotrzebowanie jest niskie, rzeczywista liczba wątków puli wątków może spaść poniżej wartości minimalnych.

Po osiągnięciu minimum pula wątków może utworzyć dodatkowe wątki lub poczekać na ukończenie niektórych zadań. Pula wątków tworzy i niszczy wątki robocze w celu optymalizacji przepływności, która jest zdefiniowana jako liczba zadań, które są wykonywane w poszczególnych jednostkach czasu. Zbyt mało wątków może nie zapewnić optymalnego wykorzystania dostępnych zasobów, podczas gdy zbyt wiele wątków może zwiększyć rywalizację o zasoby.

Ostrzeżenie

Możesz użyć ThreadPool.SetMinThreads metody , aby zwiększyć minimalną liczbę bezczynnych wątków. Jednak niepotrzebne zwiększanie tych wartości może powodować problemy z wydajnością. Jeśli zbyt wiele zadań rozpoczyna się w tym samym czasie, wszystkie z nich mogą wydawać się powolne. W większości przypadków pula wątków będzie działać lepiej za pomocą własnego algorytmu przydzielania wątków.

Korzystanie z puli wątków

Najprostszym sposobem korzystania z puli wątków jest użycie biblioteki równoległej zadań (TPL). Domyślnie typy TPL, takie jak Task i Task<TResult>, używają wątków puli wątków do uruchamiania zadań.

Można również użyć puli wątków, wywołując ThreadPool.QueueUserWorkItem z kodu zarządzanego (lub ICorThreadpool::CorQueueUserWorkItem w kodzie niezarządzanym) i przekazując delegata System.Threading.WaitCallback reprezentującego metodę, która wykonuje zadanie.

Innym sposobem użycia puli wątków jest kolejkowanie elementów roboczych związanych z operacją oczekiwania poprzez użycie ThreadPool.RegisterWaitForSingleObject metody i przekazanie argumentu System.Threading.WaitHandle, który w przypadku zasygnalizowania lub upływu czasu wywołuje metodę reprezentowaną przez delegata System.Threading.WaitOrTimerCallback. Wątki puli wątków są używane do wywoływania metod wywołania zwrotnego.

Aby zapoznać się z przykładami, sprawdź przywołyne strony interfejsu API.

Pomijanie kontroli zabezpieczeń

Pula wątków udostępnia również metody ThreadPool.UnsafeQueueUserWorkItem oraz ThreadPool.UnsafeRegisterWaitForSingleObject. Używaj tych metod tylko wtedy, gdy masz pewność, że stos wywołującego jest nieistotny dla jakichkolwiek kontroli zabezpieczeń, które są przeprowadzane podczas realizacji zadania w kolejce. ThreadPool.QueueUserWorkItem i ThreadPool.RegisterWaitForSingleObject przechwytują stos wywołującego, który jest scalany ze stosem wątku puli wątków, gdy wątek zaczyna wykonywać zadanie. Jeśli wymagane jest sprawdzenie zabezpieczeń, należy sprawdzić cały stos. Mimo że kontrola zapewnia bezpieczeństwo, ma również wpływ na wydajność.

Kiedy nie należy używać wątków z puli

Istnieje kilka scenariuszy, w których należy utworzyć własne wątki i zarządzać nimi zamiast używać wątków z puli:

  • Wymagany jest wątek pierwszego planu.
  • Musisz ustawić określony priorytet dla wątku.
  • Masz zadania, które powodują zablokowanie wątku przez długi czas. Pula wątków ma maksymalną liczbę wątków, więc duża liczba zablokowanych wątków puli wątków może uniemożliwić uruchamianie zadań.
  • Należy umieścić wątki w jednym wątkowym mieszkaniu. Wszystkie ThreadPool wątki znajdują się w modelu wielowątkowego apartamentu.
  • Musisz mieć stabilną tożsamość skojarzoną z wątkiem lub przeznaczyć wątek na zadanie.

Zobacz także