Krótkie pytanie:
Czy ktoś napotkał problem przy użyciu pojedynczego .NET HttpClient, w którym aplikacja przywiązuje procesor do 100%, dopóki nie zostanie ponownie uruchomiony?.NET: 100% użycie procesora w HttpClient ze względu na słownik?
Szczegóły:
biegnę usługa systemu Windows, który wykonuje ciągłą, ETL w oparciu o harmonogram. Jeden z wątków synchronizujących dane od czasu do czasu po prostu umiera lub zaczyna tracić kontrolę i mocuje procesor w 100%.
Miałem szczęście zobaczyć, że dzieje się to na żywo, zanim ktoś po prostu ponownie uruchomił usługę (standardowa poprawka) i był w stanie pobrać plik zrzutu.
Ładowanie tego w WinDbg (w/SOS i SOSEX), Stwierdziłem, że mam około 15 wątków (podzadania głównego wątku przetwarzania), wszystkie działające z identycznymi śladami stosu. Jednak nie pojawiają się żadne zakleszczenia. TO ZNACZY. wątki o wysokim stopniu wykorzystania działają, ale nigdy nie kończą.
Rzeczony segment stosu ślad następująco (adresy pominięta):
System.Collections.Generic.Dictionary`2[[System.__Canon, mscorlib],[System.__Canon, mscorlib]].FindEntry(System.__Canon)
System.Collections.Generic.Dictionary`2[[System.__Canon, mscorlib],[System.__Canon, mscorlib]].TryGetValue(System.__Canon, System.__Canon ByRef)
System.Net.Http.Headers.HttpHeaders.ContainsParsedValue(System.String, System.Object)
System.Net.Http.Headers.HttpGeneralHeaders.get_TransferEncodingChunked()
System.Net.Http.Headers.HttpGeneralHeaders.AddSpecialsFrom(System.Net.Http.Headers.HttpGeneralHeaders)
System.Net.Http.Headers.HttpRequestHeaders.AddHeaders(System.Net.Http.Headers.HttpHeaders)
System.Net.Http.HttpClient.SendAsync(System.Net.Http.HttpRequestMessage, System.Net.Http.HttpCompletionOption, System.Threading.CancellationToken)
...
[Our Application Code]
Według this article (i innych Znalazłem), wykorzystanie słowników jest nie pętle wątku bezpieczny i nieskończone są możliwe (podobnie jak zwykłe awarie), jeśli uzyskujesz dostęp do słownika w sposób wielowątkowy.
ALE Nasz kod aplikacji nie używa jawnie słownika. Więc gdzie jest słownik wspomniany w śledzeniu stosu?
Po przejściu przez .NET Reflector, to pojawia się, który HttpClient używa słownika do przechowywania wartości, które zostały skonfigurowane we właściwości "DefaultRequestHeaders". Każde żądanie, które otrzyma od HttpClient, wywołuje wyliczenie pojedynczego, niezawierającego wątków słownika (w celu dodania domyślnych nagłówków do żądania), które potencjalnie mogłoby w nieskończoność obrócić (lub zabić) wątki, jeśli pojawia się korupcja.
Firma Microsoft stwierdziła bez ogródek, że klasa HttpClient jest wątkowo bezpieczna. Ale wydaje mi się, że nie jest to już prawdą, jeśli jakiekolwiek nagłówki zostały dodane do DefaultRequestHeaders z HttpClient.
Moja analiza wydaje się wskazywać, że jest to prawdziwy problem root, a łatwym rozwiązaniem jest po prostu nigdy nie używać DefaultRequestHeaders, gdzie HttpClient może być używany w sposób wielowątkowy.
Jednak szukam jakiegoś potwierdzenia, że nie szczerzę niewłaściwego drzewa. Jeśli jest to poprawne, wydaje się, że jest to błąd w strukturze .NET, który automatycznie mam wątpliwości.
Przykro nam z powodu ważnego pytania, ale dziękuję za wszelkie uwagi, które możesz wnieść.
to jest ich standardowy moduł z zabezpieczeniem wątku: "Dowolne publiczne statyczne (udostępnione w języku Visual Basic) elementy tego typu są bezpieczne dla wątków. Żadne elementy instancji nie mają gwarancji, że są bezpieczne dla wątków." –
proszę podać [mcve] –
Dlaczego klient Http jest singletonem? Wydaje mi się, że najłatwiejszą opcją byłoby po prostu pozwolić każdemu wątkowi utworzyć i użyć własnej instancji. – pquest