Práticas recomendadas de confiabilidadeReliability Best Practices

As seguintes regras de confiabilidade estão orientadas ao SQL Server. No entanto, eles também se aplicam a qualquer aplicativo para servidores baseado em host.The following reliability rules are oriented to SQL Server; however, they also apply to any host-based server application. É extremamente importante que os servidores como o SQL Server não tenham perda de recursos e não fiquem inoperantes.It is extremely important that servers such as SQL Server not leak resources and not be brought down. No entanto, isso não pode ser feito para escrever código de recuo para cada método que altera o estado de um objeto.However, that cannot be done by writing back-out code for every method that alters an object’s state. A meta é não gravar código gerenciado 100 por cento confiável que se recuperará de erros em todos os locais com o código de recuo.The goal is not to write 100 percent reliable managed code that will recover from any errors in every location with back-out code. Isso seria uma tarefa difícil, com pouca probabilidade de êxito.That would be a daunting task with little chance of success. O CLR (Common Language Runtime) não pode fornecer com facilidade garantias suficientemente fortes para que o código gerenciado possa tornar a tarefa de escrever código perfeito viável.The common language runtime (CLR) cannot easily provide strong enough guarantees to managed code to make writing perfect code feasible. Observe que, diferentemente do ASP.NET, o SQL Server usa somente um processo que não pode ser reciclado sem a interrupção de um banco de dados por um período de tempo inaceitavelmente longo.Note that unlike ASP.NET, SQL Server uses only one process that cannot be recycled without taking a database down for an unacceptably long time.

Com essas garantias mais fracas e em execução em um único processo, a confiabilidade é baseada no encerramento de threads ou na reciclagem de domínios do aplicativo quando necessário, além tomar precauções para garantir que os recursos do sistema operacional, tais como memória ou identificadores, não vazem.With these weaker guarantees and running in a single process, reliability is based on terminating threads or recycling application domains when necessary and taking precautions to ensure operating system resources such as handles or memory are not leaked. Mesmo com essa restrição de confiabilidade mais simples, ainda há um requisito de confiabilidade significativo:Even with this simpler reliability constraint, there is still a significant reliability requirement:

  • Nunca perder recursos do sistema operacional.Never leak operating system resources.

  • Identificar todos os bloqueios gerenciados em todos os formulários para o CLR.Identify all managed locks in all forms to the CLR.

  • Nunca interromper o estado compartilhado entre domínios do aplicativo, permitindo que a reciclagem AppDomain funcionasse sem problemas.Never break cross-application domain shared state, allowing AppDomain recycling to function smoothly.

Embora seja teoricamente possível escrever código gerenciado para tratar exceções ThreadAbortException, StackOverflowException e OutOfMemoryException, esperar que os desenvolvedores escrevam um código tão robusto em todo um aplicativo é pouco razoável.Although it is theoretically possible to write managed code to handle ThreadAbortException, StackOverflowException, and OutOfMemoryException exceptions, expecting developers to write such robust code throughout an entire application is unreasonable. Por esse motivo, as exceções fora de banda resultam no encerramento do thread em execução; e se o thread encerrado estava editando o estado compartilhado, o que pode ser determinado dependendo de o thread manter ou não um bloqueio, o AppDomain é descarregado.For that reason, out-of-band exceptions result in the executing thread being terminated; and if the terminated thread was editing shared state, which can be determined by whether the thread holds a lock, then the AppDomain is unloaded. Quando um método que estiver editando o estado compartilhado for encerrado, o estado será corrompido porque não é possível gravar código de recup confiável para atualizações para estado compartilhado.When a method that is editing shared state is terminated, the state will be corrupt because it is not possible to write reliable back-out code for updates to shared state.

No .NET Framework versão 2.0, o único host que exige confiabilidade é o SQL Server.In the .NET Framework version 2.0, the only host that requires reliability is SQL Server. Se o assembly será executado no SQL Server, você deverá fazer o trabalho de confiabilidade para todas as partes do assembly, mesmo se houver recursos específicos que ficarão desabilitados quando em execução no banco de dados.If your assembly will be run on SQL Server you should do the reliability work for every part of that assembly, even if there are specific features that are disabled when running in the database. Isso é necessário porque o mecanismo de análise de código examina o código no nível de assembly e não pode diferenciar o código desabilitado.This is required because the code analysis engine examines code at the assembly level and cannot differentiate disabled code. Outra consideração sobre a programação do SQL Server é que o SQL Server executa tudo em um processo e a reciclagem de AppDomain é usada para limpar todos os recursos como memória e identificadores do sistema operacional.Another SQL Server programming consideration is that SQL Server runs everything in one process, and AppDomain recycling is used for cleaning up all resources such as memory and operating system handles.

Você não pode depender de finalizadores ou destruidores ou blocos try/finally para código de recuo.You cannot depend on finalizers or destructors or try/finally blocks for back-out code. Eles podem ser interrompidos ou não chamados.They might be interrupted or not called.

Exceções assíncronas podem ser geradas em locais inesperados, possivelmente em toda instrução do computador: ThreadAbortException, StackOverflowException e OutOfMemoryException.Asynchronous exceptions can be thrown in unexpected locations, possibly every machine instruction: ThreadAbortException, StackOverflowException, and OutOfMemoryException.

Threads gerenciados não são necessariamente threads Win32 em SQL; eles podem ser fibras.Managed threads are not necessarily Win32 threads in SQL; they might be fibers.

É muito difícil alterar um estado compartilhado mutável entre domínios do aplicativo ou em todo o processo com segurança e isso deve ser evitado sempre que possível.Process-wide or cross-application domain mutable shared state is extremely difficult to alter safely and should be avoided whenever possible.

Condições de falta de memória não são raras no SQL Server.Out-of-memory conditions are not rare in SQL Server.

Se bibliotecas hospedadas no SQL Server não atualizarem corretamente o estado compartilhado, há uma grande probabilidade de que o código não se recuperará até o banco de dados ter sido reiniciado.If libraries hosted in SQL Server do not correctly update their shared state, there is a high probability that the code will not recover until the database has been restarted. Além disso, em alguns casos extremos, é possível que isso possa causar falha no processo do SQL Server, fazendo com que o banco de dados seja reinicializado.Additionally, in some extreme cases, it is possible this might cause the SQL Server process to fail, causing the database to reboot. Reinicializar o banco de dados pode deixar um site da Web inoperante ou afetar as operações da empresa, afetando a disponibilidade.Rebooting the database can take down a Web site or affect company operations, hurting availability. Uma perda lenta de recursos de sistema operacional como memória ou identificadores pode fazer com que o servidor eventualmente falhe ao alocar identificadores sem possibilidade de recuperação; também é possível que o desempenho do servidor se degrade lentamente e reduza a disponibilidade de aplicativos do cliente.A slow leak of operating system resources such as memory or handles may cause the server to eventually fail allocating handles with no possibility of recovery, or potentially the server may slowly degrade in performance and reduces a customer’s application availability. É claro que queremos evitar esses cenários.Clearly we want to avoid these scenarios.

Regras de práticas recomendadasBest practice rules

A introdução se concentrou no que a revisão de código para o código gerenciado que é executado no servidor precisaria capturar para aumentar a estabilidade e a confiabilidade do framework.The introduction focused on what the code review for the managed code that runs in the server would have to catch to increase the stability and reliability of the framework. Todas essas verificações são uma boa prática em geral e uma necessidade absoluta no servidor.All these checks are good practice in general and an absolute must on the server.

No caso de uma restrição de recurso ou um deadlock, o SQL Server anulará um thread ou subdividirá um AppDomain.In the face of a dead lock or resource constraint, SQL Server will abort a thread or tear down an AppDomain. Quando isso acontece, o único elemento que certamente está em execução é o código de recuo em uma CER (região de execução restrita).When this happens, only back-out code in a constrained execution region (CER) is guaranteed to be run.

Usar SafeHandle para evitar vazamentos de recursosUse SafeHandle to avoid resource leaks

No caso de um descarregamento de AppDomain, você não pode depender de blocos finally ou finalizadores serem executados, portanto, é importante abstrair todo acesso a recursos do sistema operacional por meio da classe SafeHandle em vez de IntPtr, HandleRef ou classes semelhantes.In the case of an AppDomain unload, you cannot depend on finally blocks or finalizers being executed, so it is important to abstract all operating system resource access through the SafeHandle class rather than IntPtr, HandleRef, or similar classes. Isso permite que o CLR acompanhe e feche os identificadores que você usa até mesmo no caso de desativação de AppDomain.This allows the CLR to track and close the handles you use even in the AppDomain tear-down case. SafeHandle estará usando um finalizador crítico que o CLR sempre executará.SafeHandle will be using a critical finalizer which the CLR will always run.

O identificador de sistema operacional é armazenado no SafeHandle desde o momento em que ele é criado até o momento em que ele é liberado.The operating system handle is stored in the safe handle from the moment it is created until the moment it is released. Não há período durante o qual um ThreadAbortException pode ocorrer para que haja perda de um identificador.There is no window during which a ThreadAbortException can occur to leak a handle. Além disso, uma invocação de plataforma faz a contagem de referências do identificador, o que permite um acompanhamento preciso do tempo de vida dele e evita um problema de segurança com uma condição de corrida entre Dispose e um método que está usando atualmente o identificador.Additionally, platform invoke will reference-count the handle, which allows close tracking of the lifetime of the handle, preventing a security issue with a race condition between Dispose and a method that is currently using the handle.

A maioria das classes que atualmente têm um finalizador apenas para limpar um identificador de sistema operacional não precisarão mais do finalizador.Most classes that currently have a finalizer to simply clean up an operating system handle will not need the finalizer anymore. Em vez disso, o finalizador estará na classe derivada SafeHandle.Instead, the finalizer will be on the SafeHandle derived class.

Observe que SafeHandle não é substituição para IDisposable.Dispose.Note that SafeHandle is not a replacement for IDisposable.Dispose. Ainda há possibilidade de contenção de recursos e vantagens de desempenho para descartar explicitamente os recursos de sistema operacional.There are still potential resource contention and performance advantages to explicitly dispose operating system resources. Observe que apenas blocos finally que descartam explicitamente os recursos podem não ser executados até a conclusão.Just realize that finally blocks that do explicitly dispose of resources may not execute to completion.

SafeHandle permite que você implemente seu próprio método ReleaseHandle que executa o trabalho para liberar o identificador, tal como passar o estado para uma rotina de liberação de identificador de sistema operacional ou liberar um conjunto de identificadores em um loop.SafeHandle allows you to implement your own ReleaseHandle method that performs the work to free the handle, such as passing state to an operating system handle freeing routine or freeing a set of handles in a loop. O CLR assegura que esse método seja executado.The CLR guarantees that this method is run. É responsabilidade do autor da implementação de ReleaseHandle assegurar que o identificador seja liberado em todas as circunstâncias.It is the responsibility of the author of the ReleaseHandle implementation to ensure that the handle is released in all circumstances. Falha em fazê-lo causará perda do identificador, o que geralmente resultará em perda de recursos nativos associados com o identificador.Failure to do so will cause the handle to be leaked, which often results in the leakage of native resources associated with the handle. Portanto, é essencial estruturar classes derivadas SafeHandle de modo que a implementação de ReleaseHandle não exija a alocação de todos os recursos que podem não estar disponíveis em tempo de invocação.Therefore it is critical to structure SafeHandle derived classes such that the ReleaseHandle implementation does not require the allocation of any resources that may not be available at invocation time. Observe que é permitido chamar os métodos que podem falhar dentro da implementação do ReleaseHandle, contanto que seu código possa lidar com tais falhas e concluir o contrato para liberar o identificador nativo.Note that it is permissible to call methods that may fail within the implementation of ReleaseHandle provided that your code can handle such failures and complete the contract to release the native handle. Para fins de depuração, ReleaseHandle tem um valor retornado Boolean que pode ser definido como false se é encontrado um erro catastrófico que impede a liberação do recurso.For debugging purposes, ReleaseHandle has a Boolean return value which may be set to false if a catastrophic error is encountered which prevents release of the resource. Isso ativará o MDA releaseHandleFailed, se habilitado, para ajudar a identificar o problema.Doing so will activate the releaseHandleFailed MDA, if enabled, to aid in identifying the problem. Ele não afeta o runtime de nenhuma outra forma; ReleaseHandle não será chamado novamente para o mesmo recurso e, consequentemente, o identificador será perdido.It does not affect the runtime in any other way; ReleaseHandle will not be called again for the same resource and consequently the handle will be leaked.

SafeHandle não é apropriado em determinados contextos.SafeHandle is not appropriate in certain contexts. Já que o método ReleaseHandle pode ser executado em um thread do finalizador GC, quaisquer identificadores que seja necessário liberar em um determinado thread não devem ser encapsulados em um SafeHandle.Since the ReleaseHandle method can be run on a GC finalizer thread, any handles that are required to be freed on a particular thread should not be wrapped in a SafeHandle.

RCWs (Runtime Callable Wrappers) podem ser limpos pelo CLR sem código adicional.Runtime callable wrappers (RCWs) can be cleaned by the CLR without additional code. Para o código que usa a invocação de plataforma e trata um objeto COM como um IUnknown* ou um IntPtr, o código deve ser reescrito para usar um RCW.For code that uses platform invoke and treats a COM object as an IUnknown* or an IntPtr, the code should be rewritten to use an RCW. SafeHandle pode não ser adequado para esse cenário devido à possibilidade de um método de liberação não gerenciado retornar a chamada em código gerenciado.SafeHandle may not be adequate for this scenario due to the possibility of an unmanaged release method calling back into managed code.

Regra de análise de códigoCode analysis rule

Use SafeHandle para encapsular recursos do sistema operacional.Use SafeHandle to encapsulate operating system resources. Não use HandleRef ou campos do tipo IntPtr.Do not use HandleRef or fields of type IntPtr.

Garantir que os finalizadores não precisem ser executados para evitar vazamento de recursos do sistema operacionalEnsure finalizers do not have to run to prevent leaking operating system resources

Examine seus finalizadores cuidadosamente para assegurar que, mesmo se eles não forem executados, um recurso crítico do sistema operacional não será perdido.Review your finalizers carefully to ensure that even if they do not run, a critical operating system resource is not leaked. Ao contrário de um descarregamento de AppDomain normal quando o aplicativo está em execução em um estado estável ou quando um servidor como o SQL Server é desligado, objetos não são finalizados durante um descarregamento de AppDomain abrupto.Unlike a normal AppDomain unload when the application is executing in a steady state or when a server such as SQL Server shuts down, objects are not finalized during an abrupt AppDomain unload. Verifique se recursos não são perdidos no caso de um descarregamento abrupto, já que a correção de um aplicativo não pode ser garantida, mas a integridade do servidor deve ser mantida evitando-se a perda de recursos.Ensure resources are not leaked in the case of an abrupt unload, since an application's correctness cannot be guaranteed, but the integrity of the server must be maintained by not leaking resources. Use SafeHandle para liberar eventuais recursos do sistema operacional.Use SafeHandle to free any operating system resources.

Certifique-se de que cláusulas finally não precisem ser executadas para evitar vazamento de recursos do sistema operacionalEnsure that finally clauses do not have to run to prevent leaking operating system resources

Não há garantia de que cláusulas finally sejam executadas fora de CERs, exigindo que os desenvolvedores de biblioteca não confiem no código dentro de um bloco finally para liberar recursos não gerenciados.finally clauses are not guaranteed to run outside of CERs, requiring library developers to not rely on code within a finally block to free unmanaged resources. Usar SafeHandle é a solução recomendada.Using SafeHandle is the recommended solution.

Regra de análise de códigoCode analysis rule

Use SafeHandle para limpar os recursos do sistema operacional, em vez de Finalize.Use SafeHandle for cleaning up operating system resources instead of Finalize. Não use IntPtr; use SafeHandle para encapsular recursos.Do not use IntPtr; use SafeHandle to encapsulate resources. Se a cláusula finally precisa ser executada, coloque-a em uma CER.If the finally clause must run, place it in a CER.

Todos os bloqueios devem passar pelo código de bloqueio gerenciado existenteAll locks should go through existing managed locking code

O CLR deve saber quando o código está em um bloqueio para que ele saiba subdividir o AppDomain em vez de apenas anular o thread.The CLR must know when code is in a lock so that it will know to tear down the AppDomain rather than just aborting the thread. Anular o thread pode ser perigoso, já que os dados operados pelo thread podem ser deixados em um estado inconsistente.Aborting the thread could be dangerous as the data operated on by the thread could be left in an inconsistent state. Portanto, todo o AppDomain deve ser reciclado.Therefore, the entire AppDomain has to be recycled. As consequências de falhar em identificar um bloqueio podem ser deadlocks ou resultados incorretos.The consequences of failing to identify a lock can be either deadlocks or incorrect results. Use os métodos BeginCriticalRegion e EndCriticalRegion para identificar regiões de bloqueio.Use the methods BeginCriticalRegion and EndCriticalRegion to identify lock regions. Eles são métodos estáticos na classe Thread que se aplicam somente ao thread atual, ajudando a impedir que um thread edite a contagem de bloqueio de outro thread.They are static methods on the Thread class that only apply to the current thread, helping to prevent one thread from editing another thread’s lock count.

Enter e Exit têm essa notificação de CLR como interna, portanto, o uso deles é recomendado, bem como o uso da instrução lock, a qual usa esses métodos.Enter and Exit have this CLR notification built in, so their usage is recommended as well as the use of the lock Statement, which uses these methods.

Outros mecanismos de bloqueio como bloqueios de rotação e AutoResetEvent devem chamar esses métodos para notificar o CLR que uma seção crítica está sendo inserida.Other locking mechanisms such as spin locks and AutoResetEvent must call these methods to notify the CLR that a critical section is being entered. Esses métodos não usam nenhum bloqueio; eles informam o CLR que o código está em execução em uma seção crítica e anular o thread poderia deixar o estado compartilhado inconsistente.These methods do not take any locks; they inform the CLR that code is executing in a critical section and aborting the thread could leave shared state inconsistent. Se você definiu seu próprio tipo de bloqueio, por exemplo, uma classe ReaderWriterLock personalizada, use esses métodos de contagem de bloqueio.If you have defined your own lock type, such as a custom ReaderWriterLock class, use these lock count methods.

Regra de análise de códigoCode analysis rule

Marcar e identificar todos os bloqueios usando BeginCriticalRegion e EndCriticalRegion.Mark and identify all locks using BeginCriticalRegion and EndCriticalRegion. Não use CompareExchange, Increment e Decrement em um loop.Do not use CompareExchange, Increment, and Decrement in a loop. Não faça uma plataforma de invocação das variantes Win32 desses métodos.Do not do a platform invoke of the Win32 variants of these methods. Não use Sleep em loop.Do not use Sleep in a loop. Não use campos voláteis.Do not use volatile fields.

O código de limpeza deve estar em um bloco finally ou catch, não seguindo um catchCleanup code must be in a finally or a catch block, Not following a catch

Código de limpeza nunca deve seguir um bloco catch; ele deve estar em um finally ou no bloco catch em si.Cleanup code should never follow a catch block; it should be in a finally or in the catch block itself. Isso deve ser uma prática recomendada normal.This should be a normal good practice. Um bloco finally é geralmente preferível porque ele executa o mesmo código de erro quando uma exceção é gerada e quando o fim do bloco try é normalmente encontrado.A finally block is generally preferred because it runs the same code both when an exception is thrown and when the end of the try block is normally encountered. No caso de uma exceção inesperada ser gerada, por exemplo uma ThreadAbortException, o código de limpeza não será executado.In the event of an unexpected exception being thrown, for example a ThreadAbortException, the cleanup code will not run. Quaisquer recursos não gerenciados que você limparia em um finally devem idealmente estar encapsulados em um SafeHandle para evitar perdas.Any unmanaged resources that you would clean up in a finally should ideally be wrapped in a SafeHandle to prevent leaks. Observe que a palavra-chave using do C# pode ser usada com eficiência para descartar objetos, incluindo identificadores.Note the C# using keyword can be used effectively to dispose of objects, including handles.

Embora a reciclagem de AppDomain possa limpar recursos no thread do finalizador, ainda é importante colocar o código de limpeza no local correto.Although AppDomain recycling can clean up resources on the finalizer thread, it is still important to put cleanup code in the correct place. Observe que, se um thread recebe uma exceção assíncrona sem manter um bloqueio, o CLR tenta encerrar o thread sem a necessidade de reciclar o AppDomain.Note that if a thread receives an asynchronous exception without holding a lock, the CLR attempts to end the thread itself without having to recycle the AppDomain. Assegurar que recursos sejam limpos cedo em vez de tarde ajuda por meio da disponibilização de mais recursos e do melhor gerenciamento do tempo de vida.Ensuring that resources are cleaned up sooner rather than later helps by making more resources available, and by better managing the lifetime. Se você não fechar explicitamente um identificador para um arquivo em algum caminho de código de erro, aguarde que o finalizador SafeHandle o limpe; na próxima vez que seu código executar, ele pode poderá falhar ao tentar acessar exatamente o mesmo arquivo, se o finalizador ainda não tiver executado.If you do not explicitly close a handle to a file in some error code path then wait for the SafeHandle finalizer to clean it up, the next time your code runs it may fail trying to access the exact same file if the finalizer has not already run. Por esse motivo, garantir que o código de limpeza existe e está funcionando corretamente ajudará a recuperar-se de falhas de modo mais claro e rápido, embora isso não seja estritamente necessário.For this reason, ensuring that cleanup code exists and works correctly will help recover from failures more cleanly and quickly, even though it is not strictly necessary.

Regra de análise de códigoCode analysis rule

O código de limpeza após catch deve estar em um bloco finally.Cleanup code after catch needs to be in a finally block. Faça chamadas para descartar em um bloco finally.Place calls to dispose in a finally block. Blocos catch devem terminar com um lançamento ou relançamento.catch blocks should end in a throw or rethrow. Embora haja exceções, tais como o código detectar se é possível estabelecer uma conexão de rede em que você pode obter uma de um grande número de exceções, qualquer código que requer a captura de um número de exceções em circunstâncias normais deve fornecer uma indicação de que o código deve ser testado para ver se terá êxito.While there will be exceptions, such as code detecting whether a network connection can be established where you might get any of a large number of exceptions, any code that requires the catching of a number of exceptions under normal circumstances should give an indication that the code should be tested to see if it will succeed.

O estado compartilhado mutável de todo o processo entre domínios de aplicativo deve ser eliminado ou usar uma região de execução restritaProcess-Wide mutable shared state between application domains should be eliminated or use a constrained execution region

Conforme descrito na introdução, pode ser muito difícil escrever código gerenciado que monitore o estado compartilhado em todo o processo entre domínios de aplicativo de maneira confiável.As described in the introduction, it can be very difficult to write managed code that monitors process-wide shared state across application domains in a reliable manner. Um estado compartilhado por todo o processo é qualquer tipo de estrutura de dados compartilhada entre domínios do aplicativo, podendo ser em código Win32, dentro do CLR ou então em código gerenciado usando comunicação remota.Process-wide shared state is any sort of data structure shared between application domains, either in Win32 code, inside the CLR, or in managed code using remoting. Qualquer estado compartilhado mutável é muito difícil de escrever corretamente em código gerenciado e qualquer estado compartilhado estático pode ser feito somente com muito cuidado.Any mutable shared state is very difficult to correctly write in managed code, and any static shared state might be done only with great care. Se você tiver um estado compartilhado por todo o computador, encontre alguma forma de eliminá-lo ou proteger o estado compartilhado usando uma CER (região de execução restrita).If you have process-wide or machine-wide shared state, find some way to eliminate it or protect the shared state using a constrained execution region (CER). Observe que qualquer biblioteca com estado compartilhado que não é identificada e corrigida pode causar falha em um host como o SQL Server, que requer um descarregamento de AppDomain limpo.Note that any library with shared state that is not identified and corrected could cause a host, such as SQL Server, that requires clean AppDomain unloading to crash.

Se o código usa um objeto COM, evite compartilhar esse objeto COM entre domínios do aplicativo.If code uses a COM object, avoid sharing that COM object between application domains.

Os bloqueios não funcionam em todo o processo ou entre domínios de aplicativo.Locks do not work process-wide or between application domains.

No passado, Enter e a instrução lock foram usados para criar bloqueios de processo global.In the past, Enter and the lock Statement have been used to create global process locks. Por exemplo, isso ocorre ao bloquear classes ágeis de AppDomain, tais como instâncias de Type de assemblies não compartilhados, objetos de Thread, cadeias de caracteres internas e algumas cadeias de caracteres compartilhadas entre domínios do aplicativo usando comunicação remota.For example, this occurs when locking on AppDomain agile classes, such as Type instances from non-shared assemblies, Thread objects, interned strings, and some strings shared across application domains using remoting. Esses bloqueios não são mais para todo o processo.These locks are no longer process-wide. Para identificar a presença de um bloqueio de entre domínios do aplicativo em todo o processo, determine se o código dentro do bloqueio usa qualquer recurso externo persistente como um arquivo em disco ou, possivelmente, um banco de dados.To identify the presence of a process-wide interapplication domain lock, determine if the code within the lock uses any external, persisted resource such as a file on disk or possibly a database.

Observe que usar um bloqueio dentro de um AppDomain pode causar problemas se o código protegido usa um recurso externo, porque esse código pode ser executado simultaneamente em vários domínios de aplicativo.Note that taking a lock within an AppDomain might cause problems if the protected code uses an external resource because that code may run simultaneously across multiple application domains. Isso pode ser um problema ao gravar para um arquivo de log ou associar a um soquete para todo o processo.This can be a problem when writing to one log file or binding to a socket for the entire process. Essas alterações significam que, com exceção de usar uma instância nomeada Mutex ou Semaphore, não há modo fácil de se obter um bloqueio global no processo usando código gerenciado.These changes mean there is no easy way, using managed code, to get a process-global lock, other than using a named Mutex or Semaphore instance. Crie código que não executa simultaneamente em dois domínios do aplicativo ou use as classes Mutex ou Semaphore.Create code that does not run in two application domains simultaneously, or use the Mutex or Semaphore classes. Se o código existente não pode ser alterado, não use um mutex nomeado do Win32 para alcançar essa sincronização, porque a execução em modo fibra significa que você não pode assegurar que um mutex será adquirido e liberado pelo mesmo thread do sistema operacional.If existing code cannot be changed, do not use a Win32 named mutex to achieve this synchronization because running in fiber mode means you cannot guarantee the same operating system thread will acquire and release a mutex. Você deve usar a classe Mutex gerenciada ou um ManualResetEvent ou AutoResetEvent nomeado ou ainda um Semaphore para sincronizar o bloqueio de código de maneira que o CLR reconheça, em vez de sincronizar o bloqueio usando código não gerenciado.You must use the managed Mutex class, or a named ManualResetEvent, AutoResetEvent, or a Semaphore to synchronize the code lock in a manner that the CLR is aware of instead of synchronizing the lock using unmanaged code.

Evite lock(typeof(MyType))Avoid lock(typeof(MyType))

Objetos Type públicos e privados em assemblies compartilhados com apenas uma cópia do código compartilhado entre todos os domínios do aplicativo também apresentam problemas.Private and public Type objects in shared assemblies with only one copy of the code shared across all application domains also present problems. Para assemblies compartilhados, há apenas uma instância de um Type por processo, o que significa que vários domínios do aplicativo compartilham exatamente a mesma instância de Type.For shared assemblies, there is only one instance of a Type per process, meaning that multiple application domains share the exact same Type instance. A execução de um bloqueio em uma instância de Type usa um bloqueio que afeta todo o processo, não apenas o AppDomain.Taking a lock on a Type instance takes a lock that affects the entire process, not just the AppDomain. Se um AppDomain usar um bloqueio em um objeto Type e depois esse thread for anulado repentinamente, ele não liberará o bloqueio.If one AppDomain takes a lock on a Type object then that thread gets abruptly aborted, it will not release the lock. Esse bloqueio poderá depois pode causar deadlock em outros domínios do aplicativo.This lock then may cause other application domains to deadlock.

Uma boa maneira de aplicar bloqueios em métodos estáticos envolve a adição de um objeto de sincronização interno estático ao código.A good way to take locks in static methods involves adding a static internal synchronization object to the code. Isso pode ser inicializado no construtor da classe se houver um, mas caso contrário, ele pode ser inicializado assim:This could be initialized in the class constructor if one is present, but if not it can be initialized like this:

private static Object s_InternalSyncObject;
private static Object InternalSyncObject
{
    get
    {
        if (s_InternalSyncObject == null)
        {
            Object o = new Object();
            Interlocked.CompareExchange(
                ref s_InternalSyncObject, o, null);
        }
        return s_InternalSyncObject;
    }
}

Então, ao usar um bloqueio, use a propriedade InternalSyncObject para obter um objeto no qual o bloqueio será usado.Then when taking a lock, use the InternalSyncObject property to obtain an object to lock on. Você não precisa usar a propriedade se você inicializou o objeto de sincronização interna no seu construtor de classe.You do not need to use the property if you have initialized the internal synchronization object in your class constructor. O código de inicialização de bloqueio de verificação dupla deve ser semelhante a este exemplo:The double checking lock initialization code should look like this example:

public static MyClass SingletonProperty
{
    get
    {
        if (s_SingletonProperty == null)
        {
            lock(InternalSyncObject)
            {
                // Do not use lock(typeof(MyClass))
                if (s_SingletonProperty == null)
                {
                    MyClass tmp = new MyClass(…);
                    // Do all initialization before publishing
                    s_SingletonProperty = tmp;
                }
            }
        }
        return s_SingletonProperty;
    }
}

Uma observação sobre o bloqueio (isso)A note about lock(this)

É geralmente aceitável usar um bloqueio em um objeto individual que é acessível publicamente.It is generally acceptable to take a lock on an individual object that is publicly accessible. No entanto, se o objeto é um objeto singleton que pode causar deadlock em um subsistema inteiro, considere usar o padrão de design acima também.However, if the object is a singleton object that might cause an entire subsystem to deadlock, consider using the above design pattern as well. Por exemplo, um bloqueio em um objeto SecurityManager pode causar um deadlock dentro de AppDomain, tornando todo o AppDomain inutilizável.For example, a lock on the one SecurityManager object could cause a deadlock within the AppDomain making the entire AppDomain unusable. É recomendável não usar um bloqueio em um objeto publicamente acessível desse tipo.It is good practice to not take a lock on a publicly accessible object of this type. No entanto, um bloqueio em uma matriz ou coleção individual geralmente não deve representar um problema.However a lock on an individual collection or array should generally not present a problem.

Regra de análise de códigoCode analysis rule

Não use bloqueios em tipos que podem ser usados em domínios do aplicativo ou não têm um forte senso de identidade.Do not take locks on types that might be used across application domains or do not have a strong sense of identity. Não chame Enter em um Type, MethodInfo, PropertyInfo, String, ValueType, Thread ou qualquer objeto que derive de MarshalByRefObject.Do not call Enter on a Type, MethodInfo, PropertyInfo, String, ValueType, Thread, or any object that derives from MarshalByRefObject.

Remova o GC. Chamadas KeepAliveRemove GC.KeepAlive calls

Uma quantidade significativa de código existente não usa KeepAlive quando deveria ou então usa quando ele não é adequado.A significant amount of existing code either does not use KeepAlive when it should or uses it when it is not appropriate. Depois de converter em SafeHandle, as classes não precisam chamar KeepAlive, supondo que elas não têm um finalizador, mas dependem de SafeHandle para finalizar os identificadores do sistema operacional.After converting to SafeHandle, classes do not need to call KeepAlive, assuming they do not have a finalizer but rely on SafeHandle to finalize the operating system handles. Embora o custo de desempenho de retenção de uma chamada para KeepAlive possa ser insignificante, a percepção de que uma chamada para KeepAlive é necessária ou suficiente para resolver um problema de tempo de vida que talvez não exista mais torna mais difícil manter o código.While the performance cost of retaining a call to KeepAlive may be negligible, the perception that a call to KeepAlive is either necessary or sufficient to solve a lifetime issue that may no longer exist makes the code more difficult to maintain. No entanto, ao usar os RCWs (Runtime Callable Wrappers) do CLR de interoperabilidade COM, KeepAlive ainda é exigido pelo código.However, when using the COM interop CLR callable wrappers (RCWs), KeepAlive is still required by code.

Regra de análise de códigoCode analysis rule

Remova KeepAlive.Remove KeepAlive.

Usar o atributo HostProtectionUse the HostProtection Attribute

O HostProtectionAttribute (HPA) fornece o uso de ações de segurança declarativa para determinar os requisitos de proteção de host, permitindo que o host impeça até mesmo código totalmente confiável de chamar determinados métodos que não são apropriados para o host especificado, tais como Exit ou Show para o SQL Server.The HostProtectionAttribute (HPA) provides the use of declarative security actions to determine host protection requirements, allowing the host to prevent even fully trusted code from calling certain methods which are inappropriate for the given host, such as Exit or Show for SQL Server.

O HPA afeta somente em aplicativos não gerenciados que hospedam o Common Language Runtime e implementam a proteção de host, como o SQL Server.The HPA affects only unmanaged applications that host the common language runtime and implement host protection, such as SQL Server. Quando aplicada, os resultados de ação de segurança na criação de uma demanda de link baseada nos recursos de host que a classe ou método expõe.When applied, the security action results in the creation of a link demand based on the host resources the class or method exposes. Se o código for executado em um aplicativo cliente ou em um servidor que não seja protegido pelo host, o atributo "evapora"; ele não é detectado e, portanto, não é aplicado.If the code is run in a client application or on a server that is not host-protected, the attribute "evaporates"; it is not detected and therefore not applied.

Importante

O objetivo desse atributo é impor diretrizes de modelo de programação específicas do host, mas não o comportamento de segurança.The purpose of this attribute is to enforce host-specific programming model guidelines, not security behavior. Embora uma demanda de link seja usada para verificar a conformidade com requisitos de modelo de programação, o HostProtectionAttribute não é uma permissão de segurança.Although a link demand is used to check for conformance to programming model requirements, the HostProtectionAttribute is not a security permission.

Se o host não tem requisitos de modelo de programação, as demandas de link não ocorrem.If the host does not have programming model requirements, the link demands do not occur.

Esse atributo identifica o seguinte:This attribute identifies the following:

  • Métodos ou classes que não se ajustam ao modelo de programação do host, mas são benignas.Methods or classes that do not fit the host programming model, but are otherwise benign.

  • Métodos ou classes que não se ajustam ao modelo de programação de host e podem levar à desestabilização do código do usuário gerenciado por servidor.Methods or classes that do not fit the host programming model and could lead to destabilizing server-managed user code.

  • Métodos ou classes que não se ajustam ao modelo de programação de host e podem levar à desestabilização do processo do servidor em si.Methods or classes that do not fit the host programming model and could lead to a destabilization of the server process itself.

Observação

Se você está criando uma biblioteca de classes que pode vir a ser chamada por aplicativos que podem vir a ser executados em um ambiente de host protegido, você deve aplicar esse atributo aos membros que expõem categorias de recursos HostProtectionResource.If you are creating a class library that is to be called by applications that may execute in a host protected environment, you should apply this attribute to members that expose HostProtectionResource resource categories. Os membros da biblioteca de classes do .NET Framework com esse atributo fazem apenas com que o chamador imediato seja verificado.The .NET Framework class library members with this attribute cause only the immediate caller to be checked. O membro da biblioteca deve também causar uma verificação de seu chamador imediato da mesma maneira.Your library member must also cause a check of its immediate caller in the same manner.

Encontre mais informações sobre HPA em HostProtectionAttribute.Please find more information on HPA in HostProtectionAttribute.

Regra de análise de códigoCode analysis rule

Para o SQL Server, todos os métodos usados para apresentar a sincronização ou threading devem ser identificados com o HPA.For SQL Server, all methods used to introduce synchronization or threading must identified with the HPA. Isso inclui métodos que compartilham o estado, que são sincronizados ou que gerenciam processos externos.This includes methods that share state, are synchronized, or manage external processes. Os valores de HostProtectionResource que afetam o SQL Server são SharedState, Synchronization e ExternalProcessMgmt.The HostProtectionResource values that impact SQL Server are SharedState, Synchronization, and ExternalProcessMgmt. No entanto, qualquer método que expõe qualquer HostProtectionResource deve ser identificado por um HPA, não apenas aqueles usando recursos que afetam o SQL.However, any method that exposes any HostProtectionResource should be identified by a HPA, not just those using resources affecting SQL.

Não bloquear indefinidamente em código não gerenciadoDo not block indefinitely in unmanaged code

Bloquear em código não gerenciado em vez de em código gerenciado pode causar um ataque de negação de serviço, pois o CLR não é capaz de anular o thread.Blocking in unmanaged code instead of in managed code can cause a denial of service attack because the CLR is not able to abort the thread. Um thread bloqueado impede que o CLR descarregue o AppDomain, pelo menos até que algumas operações extremamente não seguras sejam feitas.A blocked thread prevents the CLR from unloading the AppDomain, at least without doing some extremely unsafe operations. O bloqueio usando um primitivo de sincronização do Windows é um exemplo claro de algo que não podemos permitir.Blocking using a Windows synchronization primitive is a clear example of something we cannot allow. O bloqueio em uma chamada para ReadFile em um soquete deve ser evitado, se possível — o ideal é que a API do Windows forneça um mecanismo para uma operação como essa para atingir o tempo limite.Blocking in a call to ReadFile on a socket should be avoided if possible — ideally the Windows API should provide a mechanism for an operation like this to time out.

Qualquer método que chame recursos nativos deve idealmente usar uma chamada de Win32 com um tempo limite razoável e finito.Any method that calls into native should ideally use a Win32 call with a reasonable, finite timeout. Se o usuário tem permissão para especificar o tempo limite, o usuário não deve ter permissão para especificar um tempo limite infinito sem alguma permissão de segurança específica.If the user is allowed to specify the timeout, the user should not be allowed to specify an infinite timeout without some specific security permission. Como diretriz, se um método será bloqueado por mais de aprox. 10 segundos, você precisará estar usando uma versão que dê suporte a tempos limite ou precisará de mais suporte a CLR.As a guideline, if a method will block for more than ~10 seconds, you need to be using a version that supports timeouts or you need additional CLR support.

Aqui estão alguns exemplos de APIs problemáticas.Here are some examples of problematic APIs. Pipes (anônimos e nomeados) podem ser criados com um tempo limite; no entanto, o código deve assegurar que ele nunca chame CreateNamedPipe nem WaitNamedPipe com NMPWAIT_WAIT_FOREVER.Pipes (both anonymous and named) can be created with a timeout; however, code must ensure it never calls CreateNamedPipe nor WaitNamedPipe with NMPWAIT_WAIT_FOREVER. Além disso, pode haver bloqueio inesperado mesmo se um tempo limite é especificado.Additionally, there can be unexpected blocking even if a timeout is specified. Chamar WriteFile em um pipe anônimo resultará em bloqueio até que todos os bytes sejam gravados, o que significa que, se o buffer tem dados não lidos, a chamada de WriteFile é bloqueada até o leitor ter liberado espaço no buffer do pipe.Calling WriteFile on an anonymous pipe will block until all bytes are written, meaning if the buffer has unread data in it, the WriteFile call will block until the reader has freed up space in the pipe’s buffer. Os soquetes devem sempre usar alguma API que respeita um mecanismo de tempo limite.Sockets should always use some API that honors a timeout mechanism.

Regra de análise de códigoCode analysis rule

Bloquear sem um tempo limite em código não gerenciado é um ataque de negação de serviço.Blocking without a timeout in unmanaged code is a denial of service attack. Não execute chamadas de invocação de plataforma para WaitForSingleObject, WaitForSingleObjectEx, WaitForMultipleObjects, MsgWaitForMultipleObjects e MsgWaitForMultipleObjectsEx.Do not perform platform invoke calls to WaitForSingleObject, WaitForSingleObjectEx, WaitForMultipleObjects, MsgWaitForMultipleObjects, and MsgWaitForMultipleObjectsEx. Não use NMPWAIT_WAIT_FOREVER.Do not use NMPWAIT_WAIT_FOREVER.

Identificar todos os recursos dependentes do STAIdentify any STA-Dependent features

Identifique qualquer código que use STAs (apartments de thread único) COM.Identify any code that uses COM single-threaded apartments (STAs). STAs são desabilitados no processo do SQL Server.STAs are disabled in the SQL Server process. Recursos que dependem de CoInitialize, assim como contadores de desempenho ou a área de transferência, devem ser desabilitados no SQL Server.Features that depend on CoInitialize, such as performance counters or the clipboard, must be disabled within SQL Server.

Garantir que os finalizadores estejam livres de problemas de sincronizaçãoEnsure finalizers are free of synchronization problems

Vários threads finalizadores podem existir em futuras versões do .NET Framework, o que significa que os finalizadores para instâncias diferentes do mesmo tipo são executados simultaneamente.Multiple finalizer threads might exist in future versions of the .NET Framework, meaning the finalizers for different instances of the same type run simultaneously. Eles não precisam ser completamente thread-safe; o coletor de lixo garante que apenas um thread executará o finalizador para uma determinada instância do objeto.They do not have to be completely thread safe; the garbage collector guarantees that only one thread will run the finalizer for a given object instance. No entanto, os finalizadores devem ser codificados para evitar deadlocks e condições de corrida quando executados simultaneamente em várias instâncias de objeto diferentes.However, the finalizers must be coded to avoid race conditions and deadlocks when running simultaneously on multiple different object instances. Ao usar qualquer estado externo, por exemplo, ao gravar em um arquivo de log em um finalizador, problemas de threading devem ser solucionados.When using any external state, such as writing to a log file, in a finalizer, threading issues must be handled. Não dependa da finalização para fornecer acesso thread-safe.Do not rely on finalization to provide thread safety. Não use o armazenamento local de thread, gerenciado ou nativo, para armazenar o estado no thread do finalizador.Do not use thread local storage, managed or native, to store state on the finalizer thread.

Regra de análise de códigoCode analysis rule

Os finalizadores devem estar livres de problemas de sincronização.Finalizers must be free of synchronization problems. Não use um estado mutável estático em um finalizador.Do not use a static mutable state in a finalizer.

Evite memória não gerenciada, se possívelAvoid unmanaged memory if possible

Memória não gerenciada pode ser perdida, assim como um identificador de sistema operacional.Unmanaged memory can be leaked, just like an operating system handle. Se possível, tente usar memória na pilha usando stackalloc ou um objeto gerenciado fixo, como a instrução fixed ou um GCHandle usando um byte[].If possible, try to use memory on the stack using stackalloc or a pinned managed object such as the fixed Statement or a GCHandle using a byte[]. O GC limpa esses elementos eventualmente.The GC eventually cleans these up. No entanto, se você precisar alocar memória não gerenciada, considere o uso de uma classe que deriva de SafeHandle para encapsular a alocação de memória.However, if you must allocate unmanaged memory, consider using a class that derives from SafeHandle to wrap the memory allocation.

Observe que há pelo menos um caso em que SafeHandle não é adequado.Note that there is at least one case where SafeHandle is not adequate. Para chamadas de método COM que alocam ou liberam memória, é comum que uma DLL aloque memória por meio de CoTaskMemAlloc e, em seguida, outra DLL libere essa memória com CoTaskMemFree.For COM method calls that allocate or free memory, it is common for one DLL to allocate memory via CoTaskMemAlloc then another DLL frees that memory with CoTaskMemFree. Usar SafeHandle nesses locais seria inadequado, já que ele tentará associar o tempo de vida da memória não gerenciada ao tempo de vida do SafeHandle em vez de permitir que outra DLL controle o tempo de vida da memória.Using SafeHandle in these places would be inappropriate since it will attempt to tie the lifetime of the unmanaged memory to the lifetime of the SafeHandle instead of allowing the other DLL control the lifetime of the memory.

Examinar todos os usos de catch (exceção)Review all uses of catch(Exception)

Blocos catch que capturam todas as exceções, em vez de uma exceção específica, agora capturarão exceções assíncronas também.Catch blocks that catch all exceptions instead of one specific exception will now catch the asynchronous exceptions as well. Examine cada bloco catch(Exception), procurando por nenhuma liberação de recursos importantes ou código de recuo que possa ser ignorado, bem como comportamento potencialmente incorreto dentro do próprio bloco catch para tratar uma ThreadAbortException, StackOverflowException ou OutOfMemoryException.Examine every catch(Exception) block, looking for no important resource releasing or backout code that might be skipped, as well as potentially incorrect behavior within the catch block itself for handling a ThreadAbortException, StackOverflowException, or OutOfMemoryException. Observe que é possível que esse código esteja registrando em log ou fazendo algumas suposições de que ele pode apenas ver determinadas exceções ou que sempre que uma exceção ocorre, ele falhou exatamente por um motivo específico.Note that it is possible this code might be logging or making some assumptions that it may only see certain exceptions, or that whenever an exception happens it failed for exactly one particular reason. Essas pressuposições talvez precisem ser atualizadas para incluir ThreadAbortException.These assumptions may need to be updated to include ThreadAbortException.

Considere a possibilidade de alterar todos os locais que capturam todas as exceções para capturar um tipo específico de exceção que você espera ser gerada, tal como uma FormatException de métodos de formatação de cadeia de caracteres.Consider changing all places that catch all exceptions to catching a specific type of exception that you expect will be thrown, such as a FormatException from string formatting methods. Isso impede que o bloco catch encontre exceções inesperadas e ajuda a garantir que o código não oculte bugs capturando exceções inesperadas.This prevents the catch block from running on unexpected exceptions and will help ensure the code does not hide bugs by catching unexpected exceptions. Como regra geral, nunca manipule uma exceção no código de biblioteca (código que requer que você capture uma exceção pode indicar uma falha de design no código que você está chamando).As a general rule never handle an exception in library code (code that requires you to catch an exception may indicate a design flaw in the code you are calling). Em alguns casos, talvez você queira capturar uma exceção e gerar um tipo de exceção diferente para fornecer mais dados.In some cases you may want to catch an exception and throw a different exception type to provide more data. Usar exceções aninhadas nesse caso, armazenando a causa real da falha na propriedade InnerException da nova exceção.Use nested exceptions in this case, storing the real cause of the failure in the InnerException property of the new exception.

Regra de análise de códigoCode analysis rule

Examine todos os blocos catch no código gerenciado que captura todos os objetos ou captura todas as exceções.Review all catch blocks in managed code that catch all objects or catch all exceptions. Em C#, isso significa sinalizar catch {} e catch(Exception) {} .In C#, this means flagging both catch {} and catch(Exception) {}. Considere tornar o tipo de exceção muito específico ou examine o código para garantir que ele não agirá de forma incorreta se detectar um tipo de exceção inesperado.Consider making the exception type very specific, or review the code to ensure it does not act in a bad way if it catches an unexpected exception type.

Não presuma que um thread gerenciado seja um Thread Win32 – é uma fibraDo not assume a managed thread is a Win32 thread – It is a Fiber

O uso do armazenamento local de thread gerenciado funciona, mas você não pode usar o armazenamento local de thread não gerenciado ou supor que o código será executado novamente no thread do sistema operacional atual.Using managed thread local storage does work, but you may not use unmanaged thread local storage or assume the code will run on the current operating system thread again. Não altere as configurações, como o local de thread.Do not change settings like the thread’s locale. Não chame InitializeCriticalSection ou CreateMutex por meio de invocação de plataforma porque eles requerem que o thread de sistema operacional que entra em um bloqueio também saia do bloqueio.Do not call InitializeCriticalSection or CreateMutex via platform invoke because they require the operating system thread that enters a lock also exit the lock. Como isso não será o caso ao usar fibras, mutexes e seções críticas do Win32 não podem ser usados no SQL diretamente.Since this will not be the case when using fibers, Win32 critical sections and mutexes cannot be used in SQL directly. Observe que a classe Mutex gerenciada não lida com essas preocupações de afinidade de thread.Note that the managed Mutex class does not handle these thread affinity concerns.

Você pode usar com segurança a maior parte do estado em um objeto Thread gerenciado, incluindo o armazenamento local de thread gerenciado e a cultura de interface do usuário atual do thread.You can safely use most of the state on a managed Thread object, including managed thread local storage and the thread’s current UI culture. Você também pode usar o ThreadStaticAttribute, que torna o valor de uma variável estática existente acessível somente pelo thread gerenciado atual (essa é outra maneira de fazer o armazenamento local de fibra no CLR).You can also use the ThreadStaticAttribute, which makes the value of an existing static variable accessible only by the current managed thread (this is another way of doing fiber local storage in the CLR). Para a programação de motivos de modelo, você não pode alterar a cultura atual de um thread durante a execução no SQL.For programming model reasons, you can not change the current culture of a thread when running in SQL.

Regra de análise de códigoCode analysis rule

O SQL Server é executado no modo de fibra; não use o armazenamento local de thread.SQL Server runs in fiber mode; do not use thread local storage. Evite chamadas de invocação de plataforma para TlsAlloc, TlsFree, TlsGetValue e TlsSetValue.Avoid platform invoke calls to TlsAlloc, TlsFree, TlsGetValue, and TlsSetValue.

Permitir que SQL Server manipule a representaçãoLet SQL Server handle impersonation

Já que a representação opera em nível de thread e o SQL pode executar em modo de fibra, o código gerenciado não deve representar usuários e não deve chamar RevertToSelf.Since impersonation operates on the thread level and SQL can run in fiber mode, managed code should not impersonate users, and should not call RevertToSelf.

Regra de análise de códigoCode analysis rule

Permita a representação de identificador do SQL Server.Let SQL Server handle impersonation. Não use RevertToSelf, ImpersonateAnonymousToken, DdeImpersonateClient, ImpersonateDdeClientWindow, ImpersonateLoggedOnUser, ImpersonateNamedPipeClient, ImpersonateSelf, RpcImpersonateClient, RpcRevertToSelf, RpcRevertToSelfEx nem SetThreadToken.Do not use RevertToSelf, ImpersonateAnonymousToken, DdeImpersonateClient, ImpersonateDdeClientWindow, ImpersonateLoggedOnUser, ImpersonateNamedPipeClient, ImpersonateSelf, RpcImpersonateClient, RpcRevertToSelf, RpcRevertToSelfEx, or SetThreadToken.

Não chamar Thread:: SuspendDo not call Thread::Suspend

A capacidade de suspender um thread pode parecer uma operação simples, mas pode causar deadlocks.The ability to suspend a thread may appear a simple operation, but it can cause deadlocks. Se um thread mantendo que um bloqueio é suspenso por um segundo thread e, em seguida, o segundo thread tenta usar o mesmo bloqueio, ocorre um deadlock.If a thread holding a lock gets suspended by a second thread and then the second thread tries taking the same lock, a deadlock occurs. Suspend pode atualmente interferir com a segurança, o carregamento de classe, a comunicação remota e a reflexão.Suspend can interfere with security, class loading, remoting, and reflection currently.

Regra de análise de códigoCode analysis rule

Não chame Suspend.Do not call Suspend. Considere o uso de um primitivo de sincronização real em vez disso, assim como um Semaphore ou ManualResetEvent.Consider using a real synchronization primitive instead, such as a Semaphore or ManualResetEvent .

Proteger operações críticas com regiões de execução restritas e contratos de confiabilidadeProtect critical operations with constrained execution regions and reliability contracts

Ao executar uma operação complexa que atualiza um status compartilhado ou que precisa de forma determinística ser totalmente bem-sucedido ou falhar totalmente, verifique se ele é protegido por uma CER (região de execução restrita).When performing a complex operation that updates a shared status or that needs to deterministically either fully succeed or fully fail, be sure that it is protected by a constrained execution region (CER). Isso garante que o código seja executado em todos os casos, até mesmo uma operação de anulação de thread abrupta ou um descarregamento de AppDomain abrupto.This guarantees that the code runs in every case, even an abrupt thread abort or an abrupt AppDomain unload.

Uma CER é um bloco try/finally específico imediatamente precedido por uma chamada para PrepareConstrainedRegions.A CER is a particular try/finally block immediately preceded by a call to PrepareConstrainedRegions.

Fazer isso instrui o compilador Just-In-Time para preparar a todo o código no bloco finally antes de executar o bloco try.Doing so instructs the just-in-time compiler to prepare all the code in the finally block before running the try block. Isso assegura que o código no bloco finally será criado e que será executado em todos os casos.This guarantees that the code in the finally block is built and will run in all cases. Não é incomum que uma CER tenha um bloco try vazio.It is not uncommon in a CER to have an empty try block. Usar uma CER protege contra anulações de thread assíncronas e exceções de falta de memória.Using a CER protects against asynchronous thread aborts and out-of-memory exceptions. Consulte ExecuteCodeWithGuaranteedCleanup para um formulário de uma CER que manipula excedentes de pilha de código excessivamente profundo.See ExecuteCodeWithGuaranteedCleanup for a form of a CER that additionally handles stack overflows for exceedingly deep code.

Consulte tambémSee also