Compartilhar via


Práticas recomendadas de confiabilidade

As seguintes regras de confiabilidade são orientadas para o SQL Server; no entanto, eles também aplicam a qualquer aplicativo de servidor baseado em host.É extremamente importante que sistema autônomo servidores, sistema autônomo o SQL servidor não vazam recursos e não ser colocados para baixo.No entanto, que não pode ser concluído escrevendo código back-out para cada método que altera o estado do objeto.O meta não é para gravar 100 % confiáveis código que irá recuperar de erros em todos os locais com back - out do código gerenciado.Essa seria uma tarefa desanimadora com pouca chance de sucesso.O common linguagem tempo de execução (CLR) não pode com com facilidade fornecer garantias fortes o suficiente para código gerenciado para tornar a escrever código perfeito viável.Observe que, ao contrário do ASP.NET, SQL servidor usa somente um processo que não pode ser reciclado sem colocar um banco de dados para baixo para um time inaceitavelmente longo.

Com essas garantias e execução em um único processo mais fraco, confiabilidade baseia-se na terminação de segmentos ou reciclagem aplicativo domínios quando necessárias e do afastamento precauções para garantir recursos do sistema operacional, sistema autônomo memória ou identificadores não são vazadas.Mesmo com essa restrição mais simples de confiabilidade, ainda há uma necessidade significativa confiabilidade:

  • Nunca vazamento de recursos do sistema operacional.

  • Identifica bloqueios todas gerenciado em todos os formulários para o CLR.

  • Nunca quebrar cross-domínio do aplicativo estado, permitindo que compartilhadoAppDomain reciclagem para funcionar sem problemas.

Embora seja teoricamente possível gravar código para manipular gerenciadoThreadAbortException, StackOverflowException, e OutOfMemoryException exceções, espera que os desenvolvedores gravar esse tipo de código robusto em todo um aplicativo ser inaceitáveis. Por esse motivo, out-of-banda exceções resultam em thread em execução que está sendo encerrado e se o thread encerrado foi editando o estado compartilhado, que pode ser determinado pelo se o thread mantém um bloquear e, em seguida, a AppDomain é descarregado. Quando um método que está editando o estado compartilhado é finalizado, o estado serão corrompido porque ele não é possível escrever código confiável de back-out para atualizações para o estado compartilhado.

No .NET estrutura versão 2.0, o host único que exige confiabilidade é o SQL servidor.Se o assembly será executado no SQL servidor faça o trabalho de confiabilidade para cada parte do assembly, mesmo se não houver recursos específicos que são desativados quando executado no banco de dados.Isso é necessário porque o mecanismo de análise de código examina código no nível do assembly e não é possível diferenciar código desabilitado.Outra consideração de programação do SQL servidor é que SQL servidor é executado tudo em um processo e AppDomain a reciclagem é usada para limpar todos sistema autônomo recursos sistema autônomo memória e sistema operacional alças.

Você não pode depender de finalizadores ou destruidores ou try/finally blocos de código de back-out. Pode estar interrompidos ou não chamados.

Exceções assíncrono podem ser lançadas em locais inesperados, possivelmente cada instrução da computador: ThreadAbortException, StackOverflowException, e OutOfMemoryException.

Threads gerenciado não são necessariamente Win32 threads no SQL; eles podem ser fibras.

Domínio todo o processo ou entre aplicativos mutável estado compartilhado é extremamente difícil alterar com segurança e deve ser evitado sempre que possível.

Condições de fora da memória não são raras no SQL servidor.

Se bibliotecas hospedadas no SQL servidor não atualizam corretamente o estado compartilhado, há uma probabilidade alta não recuperará o código depois que o banco de dados for reiniciado.Além disso, em alguns casos extremos, é possível que isso pode ser com que o processo de SQL servidor falhar, fazendo com que o banco de dados reinicializar.Reinicializar o banco de dados pode desativar um site da Web ou afetam as operações da empresa, afetando a disponibilidade.Um vazamento de recursos de sistema operacional, sistema autônomo memória ou sistema autônomo alças de lento pode causar falha eventualmente alças alocar com nenhuma possibilidade de recuperação no servidor, ou potencialmente o servidor lentamente pode degradar o desempenho e reduz a disponibilidade dos aplicativos do cliente.Claramente, queremos evitar essas situações.

As regras de prática

A introdução voltado para o que a análise do código para o código gerenciado é executado no servidor teria catch para aumentar a estabilidade e confiabilidade da estrutura.Todas essas verificações são uma mercadoria prática em geral e um absoluto necessário no servidor.

Diante de uma restrição de bloquear ou recurso inativa, o SQL servidor irá anular um thread ou subdividir um AppDomain. Quando isso acontece, código de back-out de apenas em uma região de execução restrita (CER) é garantido para ser executado.

Usar o SafeHandle para evitar vazamentos recurso

No caso de um AppDomain descarregar, você não pode depender finally blocos ou que está sendo executados, portanto, é importante abstrair o sistema operacional todos os finalizadores recurso acessar por meio do SafeHandle classe em vez de IntPtr, HandleRef, ou classes semelhantes. Isso permite que o CLR rastrear e fechar as alças de que você usar até mesmo o AppDomain caso de subdivisão para baixo. SafeHandle usará um finalizador crítico que o CLR sempre será executado.

O identificador do sistema operacional é armazenado na SafeHandle a partir do momento em que elas são criadas até o momento em que ele seja liberado.Não há nenhuma janela durante o qual um ThreadAbortException pode ocorrer a perda de uma alça de. Além disso, será o identificador, que permite o acompanhamento perto da tempo de vida do identificador, impedindo que um problema de segurança com uma condição de corrida entre contagem de referência de invocação de plataformaDispose e um método que está usando a alça.

A maioria das classes que tem atualmente um finalizador para simplesmente limpar um sistema operacional manipular não precisarão mais o finalizador.Em vez disso, o finalizador será o SafeHandle classe derivada.

Observe que SafeHandle não é uma substituição para IDisposable.Dispose. Há recursos ainda possíveis vantagens contenção e desempenho explicitamente descartar os recursos do sistema operacional.Apenas perceber que finally blocos explicitamente descartar os recursos não podem executar até a conclusão.

SafeHandle permite que você implemente suas próprias ReleaseHandle método que realiza o trabalho para liberar o identificador, sistema autônomo o estado de passagem para um identificador de sistema operacional liberar rotina ou liberar um conjunto de alças em um loop. O CLR garante que esse método é executado.É responsabilidade do autor do ReleaseHandle implementação para garantir que o identificador é liberado em todas as circunstâncias. Se isso haverá a alça para vazamento, que geralmente resultados em perda de recursos nativo associados com a alça.Por isso é importante estruturar SafeHandle classes derivadas de modo que o ReleaseHandle implementação não requer a alocação de quaisquer recursos que podem não estar disponível em time de chamada. Observe que é permitido a telefonar de métodos que pode falhar na implementação de ReleaseHandle desde que seu código pode lidar com essas falhas e concluir o contrato para liberar o identificador nativo. Para fins, de depuraçãoReleaseHandle tem um Boolean retornar o valor que pode ser definida para false Se for encontrado um erro catastrófico que impede que a versão do recurso. Isso ativará o releaseHandleFailed MDA MDA, se ativado, para ajudar a identificar o problema. Ela não afeta o tempo de execução de qualquer Outros forma; ReleaseHandle não será chamada novamente para o mesmo recurso e conseqüentemente vazamento de identificador.

SafeHandle não é apropriado em determinados contextos. Desde o ReleaseHandle método pode ser executado em um GC thread do finalizador, os identificadores são necessários para ser liberado em um determinado thread não devem ser dispostos em um SafeHandle.

Os tempo de execução callable wrappers (RCWs) podem ser limpos pelo CLR sem código adicional.Para obter um código que use invocação de plataforma e trata de um objeto COM sistema autônomo um IUnknown* ou um IntPtr, o código deve ser reescrito para usar um RCW. SafeHandle pode não ser adequadas para esse cenário devido à possibilidade de um método de versão não gerenciado chamar de volta em código gerenciado.

Regra de análise de código

Use SafeHandle para encapsular os recursos do sistema operacional. Não use HandleRef ou campos de tipo IntPtr.

Certifique-se de finalizadores não são necessário executar para impedir Leaking vazamento Brazilian OS recursos

Revise os finalizadores cuidadosamente para garantir que, mesmo se eles não executam, um recurso críticos do sistema operacional não é perdido.Ao contrário de um normal AppDomain descarregar quando o aplicativo está em execução em um estado estável ou quando um servidor, sistema autônomo o SQL Server é desligado, objetos não são finalizadas durante um abrupta AppDomain descarrega. Certifique-se de recursos não são perdidos em caso de um descarregar abrupta, como correção do aplicativo não pode ser garantida, mas a integridade do servidor deve ser mantida pelo não vazamento de recursos.Use SafeHandle para disponível quaisquer recursos de sistema operacional.

Garantir que finalmente cláusulas não é necessário executar para impedir Leaking vazamento Brazilian OS recursos

finally cláusulas não há garantia executado fora das CERs, exigir que os desenvolvedores de bibliotecas não depender de código dentro de um finally bloco para liberar recursos não gerenciados. Usando SafeHandle é a solução recomendada.

Regra de análise de código

Use SafeHandle para a limpeza dos recursos do sistema operacional em vez de Finalize. Não use IntPtr; use SafeHandle para encapsular os recursos. Se o finalmente cláusula deve executar, coloque-a em uma CER.

Todos os bloqueios devem ir através do código de bloqueio gerenciado existente

O CLR deve saber quando o código está em um bloquear para que ele saiba para subdividir o AppDomain em vez de apenas anulando o thread. Anular o thread pode ser perigosa sistema autônomo dados operados pelo thread podem ser deixados no estado divergente.Portanto, o inteiro AppDomain tem de ser reciclado. As conseqüências de não identificar um bloquear podem ser deadlocks ou resultados incorretos.Use os métodos BeginCriticalRegion e EndCriticalRegion Identifique as regiões de bloquear. Eles são métodos estático na Thread classe que se aplicam somente ao segmento corrente, ajudando a evitar um segmento da edição de contagem de bloqueios de segmento.

Enter e Exit têm esta notificação de CLR incorporada, portanto, seu uso é recomendado, bem sistema autônomo o uso da bloquear instrução (Referência C#), que usa esses métodos.

Outros mecanismos de bloqueio, sistema autônomo bloqueios de rotação e AutoResetEvent deve chamar esses métodos para notificar o CLR se uma seção crítica está sendo inserida. Esses métodos não terão nenhum bloqueio; eles informar ao CLR que o código está sendo executado em uma seção crítica e anular o thread poderia deixar estado compartilhado divergente.Se você tiver definido o seu próprio tipo de bloquear, sistema autônomo um personalizado ReaderWriterLock classe, usar esses métodos de contagem de bloquear.

Regra de análise de código

Marcar e identificar todos os bloqueios usando BeginCriticalRegion e EndCriticalRegion. Não use CompareExchange, Increment, e Decrement em um loop. Não faça uma invocação de plataforma das variantes do Win32 desses métodos.Não use Sleep em um loop. Não use campos volátil.

Limpeza de código deve ser em um finalmente ou um catch bloco, não seguir um problema

Código de limpeza nunca deve seguir um catch bloco; ele deve estar em um finally ou do catch bloquear a mesmo. Isso deve ser uma mercadoria prática normal.A finally bloco é geralmente preferido porque ele executa o código mesmo quando uma exceção é lançada e quando o participante das try bloco é normalmente encontrado. No caso de uma exceção inesperada que está sendo lançada, por exemplo um ThreadAbortException, o código de limpeza não será executado. Qualquer recurso não gerenciado deve limpar um finally o ideal é que deve ser disposto em um SafeHandle Para evitar vazamentos. Observe o translation from VPE for Csharp using palavra-chave pode ser usado efetivamente descarte de objetos, incluindo alças.

Embora AppDomain a reciclagem pode limpar recursos no thread do finalizador, é importante colocar código de limpeza no lugar correto. Observe que se um thread recebe uma exceção assíncrono sem mantendo um bloquear, o CLR tenta participante thread sem a necessidade de reciclar o AppDomain. Garantir que recursos são limpos mais cedo em vez de ajuda mais recente por disponibilizar mais recursos e gerenciar melhor a tempo de vida.Se você não fechar explicitamente um identificador para um arquivo em algum caminho de código de erro, em seguida, aguarde o SafeHandle finalizador para limpá-lo, na próxima vez que seu código é executado pode falhar, tentar acessar o mesmo arquivo exato, se o finalizador já não tiver executado. Por esse motivo, garantindo que o código de limpeza existe e funciona corretamente ajuda a recuperar de falhas mais clareza e rapidamente, embora não seja estritamente necessário.

Regra de análise de código

Código de limpeza após catch precisa estar em um finally bloco. Fazer chamadas a dispose em um bloco finally.catch blocos devem terminar com uma throw ou relançar. Embora haja exceções, sistema autônomo código detectando se uma conexão de rede pode ser estabelecida onde você pode receber qualquer uma de um grande número de exceções, qualquer código que exige 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 ela terá êxito.

Todo o processo mutável estado compartilhado entre domínios de aplicativo deve ser eliminada ou usar uma região de execução restrita

Conforme descrito na introdução, pode ser muito difícil escrever código gerenciado que monitora o estado compartilhado de todo o processo em domínios de aplicativo de maneira confiável.Todo o processo o estado compartilhado é qualquer tipo de estrutura de dados compartilhado entre domínios de aplicativos, no código do Win32, dentro do CLR, ou em código gerenciado usando comunicação remota.Qualquer estado compartilhado mutável é muito difícil escrever corretamente em código gerenciado, e qualquer estado compartilhado estático pode ser concluído apenas com muito cuidado.Se você tem todo o processo ou de computador de estado compartilhado, arranjar uma maneira de eliminá-lo ou proteger o estado compartilhado com uma região de execução restrita (CER).Observe que qualquer biblioteca com o estado compartilhado que não identificada e corrigida poderia causar um host, sistema autônomo o SQL servidor, que requer limpa AppDomain Descarregando falhar.

Se o código utiliza um objeto COM, evite esse objeto COM entre domínios de aplicativo de compartilhamento.

Bloqueios não funcionam todo o processo ou entre domínios de aplicativo.

No passado, Enter e o bloquear instrução (Referência C#) foram usados para criar os bloqueios de processo global. Por exemplo, isso ocorre quando o bloqueio no AppDomain ágil classes, sistema autônomo Type instâncias de assemblies não compartilhado, Thread objetos, seqüências de caracteres interned e algumas cadeias de caracteres compartilhadas entre domínios de aplicativo usando o sistema de interação remota. Esses bloqueios não são mais todo o processo.Para identificar a presença de um domínio interapplication todo o processo de bloquear, determine se o código dentro do bloquear usa qualquer recurso externo, persistente, sistema autônomo um arquivo no disco ou possivelmente um banco de dados.

Observe que um bloquear dentro de um levandoAppDomain pode causar problemas se o código protegido usa um recurso externo como esse código pode ser executado simultaneamente em vários domínios de aplicativo. Isso pode ser um problema ao gravar para arquivo de um log ou vinculação a um soquete para todo o processo.Essas alterações significam não existe uma maneira fácil, usando código gerenciado, para obter um bloquear de processo global diferente usando uma chamada Mutex ou Semaphore instância. Criar um código não executado simultaneamente em dois domínios de aplicativo ou use o Mutex ou Semaphore classes. Se código existente não pode ser alterado, fazer uso não irá adquirir um mutex nomeado Win32 atingir essa sincronização porque a execução no modo fibra significa que você não pode garantir o mesmo thread do sistema operacional e versão um mutex.Você deve usar o gerenciado Mutex classe ou um nome ManualResetEvent, AutoResetEvent, ou um Semaphore Para sincronizar o bloquear de código de forma que o CLR está ciente em vez da sincronização de bloquear usando o código não gerenciado.

Evitar bloquear(typeof(MyType))

Públicos e privados Type objetos em módulos (assemblies) compartilhados com apenas uma cópia do código compartilhado em todos os domínios de aplicativo também problemas presentes. Para assemblies compartilhados, há apenas uma instância de um Type por processo, que significa que vários domínios do aplicativo compartilham os exatamente igual Type instância. Fazer um bloquear em um Type instância tem um bloquear afeta todo o processo, não apenas o AppDomain. Se um AppDomain leva um bloquear em um Type objeto depois que o thread obtém anulado abruptamente, ela não liberar o bloquear. Em seguida, o bloquear pode causar outros domínios de aplicativo deadlock.

Uma mercadoria maneira de fazer bloqueios em métodos estáticos envolve adicionar um objeto de sincronização interna estático ao código.Isso pôde ser inicializado no construtor da classe caso haja algum, mas se não podem ser inicializado como este:

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;
    }
}

Quando tomar um bloqueio, usar o InternalSyncObject propriedade para obter um objeto para bloquear no. Não é necessário usar a propriedade se tiver inicializado o objeto de sincronização interna no seu construtor de classe.O código de inicialização de bloquear de verificação dupla deve parecer com este exemplo:

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 bloquear(this)

É geralmente aceitável usar um bloquear em um objeto individual que é acessível publicamente.No entanto, se o objeto for um objeto singleton que pode causar um subsistema inteiro para travamento, considere a possibilidade de usar o padrão de design acima também.Por exemplo, um deadlock na um SecurityManager objeto pode causar um deadlock dentro do AppDomain fazer todo o AppDomain inutilizável. É recomendável não usar um bloquear em um objeto acessível publicamente desse tipo.No entanto um bloquear de uma matriz ou coleção individual geralmente não deve representar um problema.

Regra de análise de código

Não são bloqueios em tipos que podem ser usados em domínios de aplicativo ou não tem um forte senso de identidade.Do not telefonar Enter em um Type, MethodInfo, PropertyInfo, String, ValueType, Thread, ou qualquer objeto que deriva de MarshalByRefObject.

Remover GC.KeepAlive chamadas

Uma quantidade significativa de código existente não usa KeepAlive Quando deve ou usa-lo quando não for apropriado. Depois de converter em SafeHandle, não são necessário chamar classes KeepAlive, supondo que eles não têm um finalizador, mas dependem SafeHandle Para finalizar os identificadores do sistema operacional. Embora o custo de desempenho de reter uma telefonar para KeepAlive pode ser desprezível, a percepção de que uma telefonar para KeepAlive é necessário ou suficientes para solucionar um problema que pode não existir mais torna mais difícil manter o código de tempo de vida. No entanto, ao usar os interoperabilidade CLR callable wrappers COM (RCWs) KeepAlive ainda é exigido pelo código.

Regra de análise de código

Remover KeepAlive.

Use o atributo de proteção de host

The HostProtectionAttribute (HPA) fornece o uso das ações de segurança declarativos para determinar sistema autônomo requisitos de proteção de host, permitindo que o host para evitar que códigos mesmo totalmente confiável chamar determinados métodos que são inapropriados para determinado host, sistema autônomo Exit ou Show para o SQL servidor.

O HPA afeta somente sistema autônomo aplicativos não gerenciados que hospedam o comuns linguagem tempo de execução e implementar proteção de host, sistema autônomo o SQL servidor.Quando aplicado, os resultados da ação de segurança na criação de uma demanda de link baseiam os recursos de host expõe a classe ou método.Se o código é executado em um aplicativo cliente ou em um servidor que não está protegido por host, o atributo "evaporates"; ele não é detectado e, portanto, não aplicado.

Observação importante:

A finalidade desse atributo é aplicar diretrizes de modelo de programação específica do host, comportamento de segurança não.Embora uma demanda de link é usada para verificar conformidade com requisitos de modelo de programação o HostProtectionAttribute não é uma permissão de segurança.

Se o host não tiver requisitos de modelo de programação, as demandas de link não ocorrem.

Este atributo identifica o seguinte:

  • Métodos ou classes que não ajuste o modelo de programação de host, mas são contrário benigno.

  • Métodos ou classes que não ajuste o host de programação do modelo e pode levar a desestabilizar o código do usuário do servidor gerenciado.

  • Métodos ou classes que não se ajustam o host de programação modelam e poderiam levar a um destabilization do processo do servidor propriamente dito.

Observação:

Se você estiver criando uma biblioteca de classes deve ser chamado por aplicativos que podem executar em um host de ambiente protegido, você deve aplicar esse atributo aos membros que expõem HostProtectionResource categorias de recursos. Os membros de biblioteca de classes .NET estrutura com esse atributo fazer com que somente o chamador imediato a ser verificado.O membro de biblioteca deve também fazer com que uma verificação do seu chamador imediato da mesma maneira.

Consulte para obter mais informações sobre HPA em HostProtectionAttribute.

Regra de análise de código

Para o SQL servidor, todos os métodos usados para introduzir a sincronização ou threading deve identificados com o HPA.Isso inclui métodos que compartilhem estado, são sincronizados ou gerenciar processos externos.The HostProtectionResource os valores que têm impacto sobre o SQL servidor são SharedState, Synchronization, e ExternalProcessMgmt. No entanto, qualquer método que expõe qualquer HostProtectionResource deve ser identificado por um HPA, não apenas aquelas que usam recursos que afetam o SQL.

Não bloco indefinidamente em código não gerenciado

O bloqueio 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 interromper o thread.Um thread bloqueado impede que o CLR descarregar o AppDomain, pelo menos sem fazer algumas operações extremamente inseguras. Bloqueando usando um Win32 primitivo de sincronização é um exemplo claro de algo que não é possível permitir que.O bloqueio em uma telefonar para ReadFile em um soquete deve ser evitado se possível — o ideal é que a API do Win32 deve fornecem um mecanismo para uma operação como esse time limite.

Qualquer método que chama nativo deve usar o ideal é que uma telefonar Win32 com um tempo limite razoável, finito.Se o usuário tiver permissão para especificar o tempo limite, o usuário não deve ter permissão para especificar um tempo limite infinito sem permissão de segurança específicas de alguns.sistema autônomo diretriz, se um método bloco por mais de cerca de 10 segundos, você precisa estar usando uma versão que ofereça suporte a tempos limites ou precisar de suporte adicional do CLR.

Aqui estão alguns exemplos de problemático API.Pipes (anônimas e nomeadas) podem ser criadas com um tempo limite; Entretanto, o código deve garantir a que ele nunca chama CreateNamedPipe nem WaitNamedPipe com NMPWAIT_WAIT_FOREVER. Além disso, pode haver inesperado bloqueando mesmo se um tempo limite é especificado. De telefonarWriteFile em um pipe anônimo será bloqueado até que todos os bytes são gravados, ou seja, se o buffer tem dados não lidos, a WriteFile telefonar será bloqueado até que o leitor tenha liberado espaço no buffer do pipe. Soquetes sempre devem usar a API de honra um mecanismo de tempo limite.

Regra de análise de código

Bloqueando sem tempo limite em código não gerenciado é um ataque de negação de serviço.Não realize invocação de plataforma chamadas para WaitForSingleObject, WaitForSingleObjectEx, WaitForMultipleObjects, MsgWaitForMultipleObjects, e MsgWaitForMultipleObjectsEx. Não use NMPWAIT_WAIT_FOREVER.

Identifique quaisquer recursos STA dependente.

Identificar qualquer código que usa COM single-threaded apartments (STAs).STAs estão desabilitados no processo do SQL servidor.Recursos que dependem da CoInitialize, sistema autônomo contadores de desempenho ou a área de transferência, deve ser desabilitado dentro do SQL servidor.

Certifique-se de finalizadores estão disponível de problemas de sincronização

Vários segmentos de finalizador podem existir em futuras versões do .NET estrutura, que significa que os finalizadores para diferentes instâncias do mesmo tipo executados simultaneamente.Eles não precisam ser completamente segura para thread; o coletor de lixo garante que apenas um thread executará o finalizador para uma ocorrência de determinado objeto.No entanto, os finalizadores devem ser codificados para evitar condições de corrida e travamentos quando executados simultaneamente em várias instâncias de objeto diferente.Ao usar qualquer estado externo, sistema autônomo gravar um arquivo de log em um finalizador, threading problemas deve ser manipulada.Não confie na finalização para fornecer acesso thread-safe.Não use armazenamento thread local, gerenciado ou nativo, para armazenar o estado da thread do finalizador.

Regra de análise de código

Os finalizadores devem estar disponível de problemas de sincronização.Não use um estado mutável estático em um finalizador.

Se possível evitar a memória não gerenciada

Memória não gerenciada pode ser perdida, como um identificador de sistema operacional.Se possível, tente usar memória na pilha usando stackalloc (Referência C#) ou um objeto gerenciado fixado, sistema autônomo o Instrução fixa (referência C#) ou um GCHandle usando um byte []. The GC eventualmente limpa esses. No entanto, se você deve alocar memória não gerenciada, considere usar uma classe que deriva de SafeHandle Para ajustar a alocação de memória.

Observe que há pelo menos um caso em que SafeHandle não é adequada. Para chamadas de método COM que alocar ou liberem memória, é comum para uma DLL alocar memória através de CoTaskMemAlloc em seguida, outra DLL libera que a memória com CoTaskMemFree. Usando SafeHandle Esses locais seria inadequado, pois ele tentará vincular a vida útil de memória não gerenciada para o tempo de vida da SafeHandle em vez de permitir que o Outros controle DLL a vida útil de memória.

Revise todos os usos do Catch(exceção)

Captura blocos que catch todas sistema autônomo exceções, em vez de uma exceção específica agora irão capturar exceções assíncrono.Examinar todos sistema autônomo blocos catch(exceção), procurando sem liberar recursos importantes ou recuo código que pode ser ignorado, bem sistema autônomo comportamento potencialmente incorreto dentro do bloco catch propriamente dito para manipular um ThreadAbortException, StackOverflowException, ou OutOfMemoryException. Observe que é possível que esse código pode fazer logon ou fazendo algumas suposições que ele pode apenas ver ou certas exceções ou que sempre que ocorrer uma exceção falhou para exatamente uma razão específica.Essas suposições talvez precise ser atualizado para incluir ThreadAbortException.

Considere alterar todas coloca esse catch todas sistema autônomo exceções a captura de um tipo específico de exceção que você espera que será lançada sistema autônomo um FormatException de seqüência de caracteres de formatação métodos. Isso evita que o bloco catch sejam executados em exceções inesperadas e ajudará a garantir que o código não oculta os bugs por capturar exceções inesperadas.sistema autônomo regra geral nunca manipular uma exceção no código da biblioteca (o código que requer que você capturar uma exceção pode indicar uma falha de design no código de chamada).Em alguns casos convém capturar uma exceção e lançar um tipo de exceção diferente para fornecer mais dados.Usar exceções aninhadas nesse caso, armazenando a real causa da falha no InnerException propriedade da nova exceção.

Regra de análise de código

Revise todos os blocos catch no código gerenciado que catch todos os objetos ou catch todas as exceções.Translation from VPE for Csharp, isso significa sinalizando ambas catch {} e catch(Exception) {}. Considere o tipo de exceção muito específicas ou revise o código para garantir que não age de forma incorreta se ele o alcança um tipo de exceção inesperado.

Não assumir um thread gerenciado é um Thread Win32 – É uma fibra

Usando o gerenciado thread local armazenamento funciona, mas não pode usar o armazenamento local de thread não gerenciado ou assumem que o código será executado novamente no thread de sistema operacional corrente.Não altere configurações, como localidade do thread.Do not telefonar InitializeCriticalSection ou CreateMutex por meio de plataforma chame porque elas exigem que insere um bloquear de thread do sistema operacional também sair do bloquear. Como esse não será o caso ao usar fibras, as seções críticas do Win32 e exclusões mútuas não podem ser usadas no SQL diretamente.Observe que o gerenciado Mutex classe não processa essas preocupações de afinidade de thread.

Você pode usar com segurança a maioria do estado em um gerenciado Thread objeto, incluindo armazenamento local de thread gerenciado e cultura UI corrente do segmento. Você também pode usar o ThreadStaticAttribute, que torna o valor de uma variável estática existente acessível somente pelo thread corrente gerenciada (essa é outra maneira de fazer o armazenamento local de fibra no CLR). Para razões de modelo de programação, não é possível alterar a cultura corrente de um thread quando executado no SQL.

Regra de análise de código

SQL servidor é executado no modo fibra; não use o armazenamento local de segmento.Evitar invocação de plataforma chamadas para TlsAlloc, TlsFree, TlsGetValue, e TlsSetValue.

Permitir que a representação do identificador SQL servidor

Como a representação opera em nível de thread e o SQL pode ser executado em modo fibra, código gerenciado não deve representar usuários e não deve chamar RevertToSelf.

Regra de análise de código

Deixar que o SQL servidor lidar com a representação.Não use RevertToSelf, ImpersonateAnonymousToken, DdeImpersonateClient, ImpersonateDdeClientWindow, ImpersonateLoggedOnUser, ImpersonateNamedPipeClient, ImpersonateSelf, RpcImpersonateClient, RpcRevertToSelf, RpcRevertToSelfEx, ou SetThreadToken.

Fazer não telefonar Thread::Suspend

A capacidade de suspender um thread pode aparecer uma operação simples, mas pode fazer com que deadlocks.Se um thread mantendo que um bloquear é suspenso por um segundo thread e, em seguida, o segundo thread tentar fazer o mesmo bloquear, ocorre um deadlock.Suspend podem interferir com segurança, carregamento de classe, comunicação remota e reflexão no momento.

Regra de análise de código

Não chame Suspend. Considere usar um primitivo de sincronização real em vez disso, sistema autônomo um Semaphore ou ManualResetEvent .

Proteger as operações críticas com regiões de execução restrita e contratos de confiabilidade

Quando executar uma operação complexa que atualiza um status compartilhado ou que precisa para deterministicamente tanto totalmente bem-sucedida ou totalmente falhar, certifique-se de que ele está protegido por uma região de execução restrita (CER).Isso garante que o código seja executado em todos os casos, até mesmo uma anulação de thread abruptas ou um abrupta AppDomain descarrega.

Uma CER é um determinado try/finally bloco imediatamente precedido por uma telefonar para PrepareConstrainedRegions.

Isso instrui o compilador just-in-time para preparar todos os códigos no bloco finally antes de executar o try bloco. Isso garante que o código a finalmente bloco é criado e será executado em todos os casos.Não é incomum em uma CER para ter um vazio try bloco. Utilizando uma CER protege contra anulações de thread assíncrono e exceções de memória insuficiente.See ExecuteCodeWithGuaranteedCleanup para um formulário de uma CER que manipula Além disso pilha excede para código muito profundo.

Consulte também

Conceitos

Programação do SQL servidor e atributos de proteção de host

Referência

System.Runtime.ConstrainedExecution