Código Gerenciado Após Estado da Thread Destruído em .NET 9 e .NET 10
No .NET 9.0.5 e posteriores (incluindo .NET 10), um aplicativo usando IronPDF sai com um erro de asserção fatal e código de saída 127.
Attempt to execute managed code after the .NET runtime thread state has been destroyed.
A Microsoft introduziu uma limpeza de thread FLS (Armazenamento Local de Fibras) mais rigorosa no .NET 9.0.5. O SO controla a ordem de execução dos callbacks FLS, o que pode acionar a finalização do CLR antes que o renderizador Chrome do IronPDF termine sua própria sequência de desligamento. Este problema é específico do Windows; Linux e macOS não são afetados. .NET 6, 7 e 8 saem normalmente. A geração de PDF do IronPDF é concluída com sucesso antes do disparo da asserção. A Microsoft registrou o problema como "Futuro" sem data de correção planejada.
Opções
Opção 1: Fazer downgrade para .NET 8 (Recomendado)
.NET 6.0.36 e .NET 8.0.26 saem normalmente. Faça downgrade do framework de destino se for necessário uma saída limpa do processo.
Opção 2: Use arquivos de resultados de teste em vez de códigos de saída no CI/CD
O trabalho de PDF é concluído com sucesso antes do disparo da asserção. Publique os resultados dos testes a partir de arquivos de resultados, em vez de depender do código de saída:
Azure DevOps:
- script: dotnet test --logger "trx" || true
- task: PublishTestResults@2
inputs:
testResultsFiles: '**/*.trx'
- script: dotnet test --logger "trx" || true
- task: PublishTestResults@2
inputs:
testResultsFiles: '**/*.trx'
GitHub Actions:
- run: dotnet test --logger "trx" || true
- uses: dorny/test-reporter@v1
with:
path: '**/*.trx'
reporter: dotnet-trx
- run: dotnet test --logger "trx" || true
- uses: dorny/test-reporter@v1
with:
path: '**/*.trx'
reporter: dotnet-trx
Opção 3: Filtre o código de saída no shell
dotnet run 2>stderr.log; EXIT=$?
if grep -q "thread state has been destroyed" stderr.log; then exit 0; else exit $EXIT; fi
dotnet run 2>stderr.log; EXIT=$?
if grep -q "thread state has been destroyed" stderr.log; then exit 0; else exit $EXIT; fi
Soluções mitigatórias conhecidas que não funcionam: Installation.SkipShutdown = true, SetErrorMode, Environment.Exit(0), e coleta manual de GC antes de sair.

