Wynik CORPROF_E_UNSUPPORTED_CALL_SEQUENCE HRESULT
CORPROF_E_UNSUPPORTED_CALL_SEQUENCE HRESULT został wprowadzony w .NET Framework wersji 2.0. .NET Framework 4 zwraca ten element HRESULT w dwóch scenariuszach:
Gdy profiler porwania wymusza resetowanie kontekstu rejestru wątku w dowolnym czasie, tak aby wątek próbował uzyskać dostęp do struktur, które są w stanie niespójnym.
Gdy profiler próbuje wywołać metodę informacyjną, która wyzwala odzyskiwanie pamięci z metody wywołania zwrotnego, która zabrania odzyskiwania pamięci.
Te dwa scenariusze zostały omówione w poniższych sekcjach.
Porwanie profilatorów
(Ten scenariusz jest przede wszystkim problemem z porwaniem profilatorów, chociaż istnieją przypadki, w których profilerzy nieuwzwalający na przejęcie mogą zobaczyć ten element HRESULT).
W tym scenariuszu profiler porwania wymusza resetowanie kontekstu rejestru wątku w dowolnym czasie, aby wątek mógł wprowadzić kod profilera lub ponownie wprowadzić środowisko uruchomieniowe języka wspólnego (CLR) za pomocą metody ICorProfilerInfo .
Wiele identyfikatorów interfejsu API profilowania zapewnia punkt do struktur danych w środowisku CLR. Wiele ICorProfilerInfo
wywołań tylko odczytuje informacje z tych struktur danych i przekazuje je z powrotem. Jednak CLR może zmienić elementy w tych strukturach w miarę uruchamiania i może używać blokad do tego celu. Załóżmy, że clR już trzymał (lub próbował uzyskać) blokadę w czasie, gdy profiler porwał wątek. Jeśli wątek ponownie wprowadza clR i próbuje podjąć więcej blokad lub inspekcji struktur, które były w trakcie modyfikacji, te struktury mogą być w stanie niespójnym. Zakleszczenia i naruszenia dostępu mogą łatwo wystąpić w takich sytuacjach.
Ogólnie rzecz biorąc, gdy profiler nie porwania wykonuje kod wewnątrz metody ICorProfilerCallback i wywołuje metodę ICorProfilerInfo
z prawidłowymi parametrami, nie powinien zakleszczać ani nie odbierać naruszenia dostępu. Na przykład kod profilera uruchamiany wewnątrz metody ICorProfilerCallback::ClassLoadFinished może poprosić o informacje o klasie, wywołując metodę ICorProfilerInfo2::GetClassIDInfo2 . Kod może otrzymać CORPROF_E_DATAINCOMPLETE HRESULT, aby wskazać, że informacje są niedostępne. Jednak nie będzie zakleszczenia ani nie otrzyma naruszenia dostępu. Te wywołania ICorProfilerInfo
są uznawane za synchroniczne, ponieważ są wykonywane z ICorProfilerCallback
metody .
Jednak zarządzany wątek, który wykonuje kod, który nie znajduje się w ICorProfilerCallback
metodzie, jest uważany za wykonywanie wywołania asynchronicznego. W .NET Framework wersji 1 trudno było określić, co może się zdarzyć w wywołaniu asynchronicznym. Połączenie może zakleszczać, ulegać awarii lub udzielić nieprawidłowej odpowiedzi. .NET Framework w wersji 2.0 wprowadzono kilka prostych kontroli, które ułatwiają uniknięcie tego problemu. W .NET Framework 2.0, jeśli wywołasz niebezpieczną ICorProfilerInfo
funkcję asynchronicznie, kończy się to niepowodzeniem z CORPROF_E_UNSUPPORTED_CALL_SEQUENCE HRESULT.
Ogólnie rzecz biorąc, wywołania asynchroniczne nie są bezpieczne. Jednak następujące metody są bezpieczne i obsługują wywołania asynchroniczne:
Aby uzyskać więcej informacji, zobacz wpis Dlaczego CORPROF_E_UNSUPPORTED_CALL_SEQUENCE w blogu interfejsu API profilowania CLR.
Wyzwalanie odzyskiwania pamięci
Ten scenariusz obejmuje profilera, który działa wewnątrz metody wywołania zwrotnego (na przykład jednej z ICorProfilerCallback
metod), która zabrania odzyskiwania pamięci. Jeśli profiler próbuje wywołać metodę informacyjną (na przykład metodę w interfejsie ICorProfilerInfo
), która może wyzwolić odzyskiwanie pamięci, metoda informacyjna kończy się niepowodzeniem z CORPROF_E_UNSUPPORTED_CALL_SEQUENCE HRESULT.
W poniższej tabeli przedstawiono metody wywołania zwrotnego, które zabraniają odzyskiwania pamięci, oraz metody informacyjne, które mogą wyzwalać odzyskiwanie pamięci. Jeśli profiler wykonuje wewnątrz jednej z wymienionych metod wywołania zwrotnego i wywołuje jedną z wymienionych metod informacyjnych, ta metoda informacyjna kończy się niepowodzeniem z CORPROF_E_UNSUPPORTED_CALL_SEQUENCE HRESULT.