Pergunta

Na minha aplicação eu tenho um formulário que inicia o processo de sincronização e para várias razões eu quero permitir que apenas uma sincronização para executar de cada vez. Então eu adicionei um campo bool estático para a minha forma indicando se a sincronização está em andamento e acrescentou um bloqueio para definir este campo como true se ele já não foi definido de modo que primeiro segmento poderia iniciar a sincronização, mas quando ele está correndo qualquer outro segmento que vai tentar iniciá-lo vai terminar.

Meu código é algo como isto:

internal partial class SynchronizationForm : Form
{
    private static volatile bool workInProgress;

    private void SynchronizationForm_Shown(object sender, EventArgs e)
    {
        lock (typeof(SynchronizationForm))
        {
            if (!workInProgress)
            {
                workInProgress = true;
            }
            else
            {
                this.Close();
            }
        }
    }
}

Isso está funcionando bem, mas quando eu executar análise de código no meu projeto que estou recebendo a seguinte mensagem de aviso:

CA2002: Microsoft.Reliability: 'SynchronizationForm.SynchronizationForm_Shown (objeto, EventArgs)' bloqueios em uma referência de tipo 'Tipo'. Substituir este com um bloqueio contra um objeto com forte identidade.

Alguém pode me explicar o que está errado com o meu código e como posso melhorá-lo para fazer o alerta foi. O que significa esse objeto tem uma forte identidade?

Foi útil?

Solução

O que é errado é que você está travando em algo público (typeof(SynchronizationForm)) que é acessível em todos os lugares do seu código e se alguns outros bloqueios de rosca sobre a mesma coisa que você começa um impasse. Em geral, é uma boa idéia para bloquear apenas em objetos estáticos particulares:

private static object _syncRoot = new object();
...
lock (_syncRoot) 
{

}

Este garante-lhe que é apenas SynchronizationForm que poderia possuir o bloqueio.

Outras dicas

A partir da MSDN explicação da regra

Um objeto é dito ter uma identidade fraca quando ele pode ser acessado diretamente através de limites de domínio de aplicativo. Um segmento que tenta adquirir um bloqueio em um objeto que tem uma identidade fraca pode ser bloqueado por um segundo segmento em um domínio de aplicativo diferente que tem um bloqueio no mesmo objeto.

Uma vez que você não pode necessariamente prever o que bloqueia outro AppDomain pode tomar, e uma vez que tais bloqueios podem precisar ser empacotado e, então, ser caro, esta regra faz sentido para mim.

O problema é que typeof (SynchronizationForm) não é um objeto de bloqueio privada, o que significa que qualquer outro pedaço de código poderia usá-lo para bloquear, o que poderia resultar em impasse. Por exemplo, se algum outro código fez isso:

var form = new SynchronizationForm();
lock(typeof(SynchronizationForm))
{
    form.SomeMethodThatCausesSynchronizationForm_ShownToBeCalled();
}

Então impasse irá ocorrer. Em vez disso você deve delcare um objeto de bloqueio privado na classe SynchronizationForm e bloqueio em que, em vez.

O objeto System.Type de uma classe pode ser convenientemente utilizado como o lock-exclusão mútua para os métodos estáticos da classe.

Fonte: http://msdn.microsoft. com / en-us / library / aa664735 (VS.71) .aspx

Para adicionar a resposta de Doug, o que você tem aqui é um mecanismo de bloqueio que só deve ser usado em métodos estáticos, sendo utilizado em um método de instância.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top