Inne odpowiedzi wydają się pomijać najważniejszy punkt:
Jeśli nie próbujesz zrównoleglać operacji intensywnie wykorzystującej procesor, aby wykonać ją szybciej w witrynie o niskim obciążeniu, nie ma sensu w ogóle używać wątku roboczego.
Dotyczy to zarówno wątków wolnych, utworzonych przez new Thread(...)
, jak i wątków roboczych w ThreadPool
odpowiedzi na QueueUserWorkItem
żądania.
Tak, to prawda, to może głodować ThreadPool
w procesie ASP.NET przez kolejkowanie zbyt wielu elementów roboczych. Uniemożliwi to ASP.NET przetwarzanie dalszych żądań. Informacje zawarte w artykule są pod tym względem dokładne; ta sama pula wątków QueueUserWorkItem
jest również używana do obsługi żądań.
Ale jeśli faktycznie umieszczasz w kolejce wystarczającą liczbę elementów roboczych, aby spowodować ten głód, powinieneś zagłodzić pulę wątków! Jeśli wykonujesz dosłownie setki operacji intensywnie wykorzystujących procesor w tym samym czasie, co dobrego przyniesie kolejny wątek roboczy do obsługi żądania ASP.NET, gdy maszyna jest już przeciążona? Jeśli napotkasz taką sytuację, musisz całkowicie przeprojektować!
W większości przypadków widzę lub słyszę, że kod wielowątkowy jest niewłaściwie używany w ASP.NET, ale nie służy do kolejkowania prac intensywnie wykorzystujących procesor. Służy do kolejkowania pracy związanej z we / wy. A jeśli chcesz wykonywać operacje we / wy, powinieneś używać wątku we / wy (port zakończenia we / wy).
W szczególności powinieneś używać wywołań zwrotnych asynchronicznych obsługiwanych przez dowolną klasę biblioteki, której używasz. Metody te są zawsze bardzo wyraźnie oznaczone; zaczynają się od słów Begin
i End
. Jak w Stream.BeginRead
, Socket.BeginConnect
, WebRequest.BeginGetResponse
, i tak dalej.
Metody te zrobić używać ThreadPool
, ale używają IOCPs, które mają nie kolidować z żądań ASP.NET. Jest to specjalny rodzaj lekkiego wątku, który może zostać „obudzony” przez sygnał przerwania z systemu I / O. W aplikacji ASP.NET zwykle masz jeden wątek we / wy na każdy wątek roboczy, więc każde żądanie może mieć w kolejce jedną operację asynchroniczną. To dosłownie setki operacji asynchronicznych bez znaczącego pogorszenia wydajności (zakładając, że podsystem we / wy może nadążyć). To o wiele więcej niż kiedykolwiek będziesz potrzebować.
Pamiętaj tylko, że delegaci asynchroniczne nie działają w ten sposób - w końcu będą używać wątku roboczego, tak jak ThreadPool.QueueUserWorkItem
. To tylko wbudowane metody asynchroniczne klas bibliotecznych .NET Framework są w stanie to zrobić. Możesz to zrobić sam, ale jest to skomplikowane i trochę niebezpieczne i prawdopodobnie wykracza poza zakres tej dyskusji.
Moim zdaniem najlepszą odpowiedzią na to pytanie jest nieużywanie wystąpienia ThreadPool
lub w tle Thread
w ASP.NET . To wcale nie jest tak, jak uruchamianie wątku w aplikacji Windows Forms, gdzie robisz to, aby interfejs użytkownika był responsywny i nie dbał o jego wydajność. W ASP.NET Twoim problemem jest przepustowość , a całe to przełączanie kontekstu we wszystkich tych wątkach roboczych absolutnie zabije Twoją przepustowość, niezależnie od tego, czy używasz programu ThreadPool
.
Proszę, jeśli piszesz kod wątkowy w ASP.NET - zastanów się, czy można go przepisać tak, aby używał wcześniej istniejących metod asynchronicznych, a jeśli nie, to zastanów się, czy naprawdę potrzebujesz kodu w ogóle działać w wątku w tle. W większości przypadków prawdopodobnie będziesz dodawać złożoność bez żadnych korzyści netto.