Compartilhar via


Como: Declarar um evento em uma interface e implementá-lo em uma classe (Guia de programação C#)

As seções a seguir descrevem os recursos e classes que podem ser usados para sincronizar o acesso a recursos em aplicativos multissegmentados.

Uma das vantagens de usar vários thread s em um aplicativo é que cada thread executa de forma assíncrona.No caso de aplicativos do Windows, essa opção permite demoradas tarefas a serem executadas no plano de fundo enquanto a janela do aplicativo e os controles permanecem responsivos.Para servidor de aplicativos, multithreading fornece a capacidade para lidar com cada solicitação de entrada com um thread diferente.Caso contrário, cada nova solicitação não poderia obter atendida até que a solicitação anterior tivesse sido totalmente satisfeita.

No entanto, a natureza assíncrono de threads significa que o acesso aos recursos, sistema autônomo identificadores de arquivos, conexões de rede e memória precisa estar coordenada.Caso contrário, dois ou mais threads poderiam acesso o mesmo recurso ao mesmo time, cada sem reconhecimento de ações do Outros.O resultado é a corrupção de dados imprevisíveis.

Para operações simples em tipos de dados numéricos, o sincronização de threads pode ser realizada com os membros a Interlocked classe. Para todos os dados de outros tipos e recursos não-seguro para thread, multithreading só podem ser com segurança executados usando as construções neste tópico.

Para obter informações detalhadas sobre a programação multithread, consulte:

O bloquear de palavras-chave

The lock palavra-chave pode ser usado para garantir que um bloco de código seja executado para conclusão sem interrupções por outros threads. Isso é conseguido obter um bloquear de exclusão mútua para um determinado objeto para a duração do bloco de código.

A lock demonstrativo começa com a palavra-chave lock, que é dado um objeto sistema autônomo um argumento e seguido de um bloco de código que deve ser executado por apenas um thread por vez. Por exemplo:

public class TestThreading
{
    private System.Object lockThis = new System.Object();

    public void Function()
    {

        lock (lockThis)
        {
            // Access thread-sensitive resources.
        }
    }

}

O argumento fornecido para o lock palavra-chave deve ser um objeto com base em um tipo de referência e é usado para definir o escopo do bloquear. No exemplo acima, o escopo de bloquear é limitado a essa função porque não há referências para o objeto lockThis existe fora da função. Se existissem como uma referência, bloquear de escopo seria estender a esse objeto.Estritamente falando, o objeto fornecido para lock é usado exclusivamente para identificar exclusivamente o recurso seja compartilhado entre vários threads, portanto, pode ser uma instância da classe arbitrário. Na prática, no entanto, esse objeto normalmente representa o recurso para o segmento que a sincronização é necessária.Por exemplo, se um objeto de recipiente deve ser usado por vários threads, em seguida, o contêiner pode ser passado para bloquear e o bloco de código sincronizado após o bloqueio poderia acessar o contêiner.sistema autônomo longo sistema autônomo contêm outros bloqueios de segmentos no mesmo antes de acessá-lo e, em seguida, acesso ao objeto é sincronizado com segurança.

Em geral, é melhor evitar o bloqueio em um public tipo, ou em instâncias de objeto além do controle do seu aplicativo. Por exemplo, lock(this) pode ser problemático se a instância pode ser acessada publicamente, pois pode bloquear código além do controle no objeto sistema autônomo bem. Isso poderia criar deadlock situações em que dois ou mais threads Aguarde o versão do mesmo objeto.Bloqueio em um tipo de dados públicos sistema autônomo vez de um objeto, pode causar problemas para o mesmo resistema autônomoon.Seqüências de caracteres literal de bloqueio é arriscado especialmente como seqüências de caracteres literal são interned common linguagem tempo de execução (CLR).Isso significa que há uma instância de determinada seqüência de caracteres literal para o programa inteiro, o mesmo objeto exato representa o literal em todos os executando domínios de aplicativo em todos os segmentos.sistema autônomo resultado, colocar um bloquear em uma seqüência de caracteres com o mesmo Sumário em qualquer lugar em bloqueios de processo do aplicativo todas sistema autônomo instâncias dessa cadeia de caracteres no aplicativo.sistema autônomo resultado, é melhor bloquear um membro particular ou protegido que não interned.Algumas classes fornecem membros especificamente para o bloqueio.The Array tipo, por exemplo, fornece SyncRoot. Muitos tipos de coleção fornecem um SyncRoot membro também.

Para obter mais informações sobre o lock palavra-chave, consulte:

Monitores

Como a lock palavra-chave, monitores impeça blocos de código em execução simultânea de vários segmentos. The Enter método permite apenas um thread para prosseguir para as instruções a seguir; todos os outros segmentos são bloqueados até que as chamadas do thread em execução Exit. Isso é exatamente como usar o lock palavra-chave. Na verdade, a lock palavra-chave é implementada com o Monitor classe. Por exemplo:

lock (x)
{
    DoSomething();
}

Isso equivale ao:

System.Object obj = (System.Object)x;
System.Threading.Monitor.Enter(obj);
try
{
    DoSomething();
}
finally
{
    System.Threading.Monitor.Exit(obj);
}

Usando o lock palavra-chave é geralmente preferido usando o Monitor classe diretamente, ambos porque lock é mais conciso e porque lock assegura que o monitor subjacente é liberado, mesmo se o código protegido lançar uma exceção. Isso é realizado com o finally palavra-chave, que executa seu bloco de código associado independentemente de se uma exceção é lançada.

Para obter mais informações sobre monitores, consulte Exemplo de tecnologia de sincronização do Monitor.

Eventos de sincronização e identificadores de espera

Usando um monitor ou um bloquear é útil para impedir a execução simultânea de thread sensíveis blocos de código, mas essas construções não permitir que um segmento para comunicar-se um evento para outro.Isso requer eventos de sincronização, que são objetos que possuem um dos dois estados, signaled e un-signaled, que pode ser usado para ativar e suspender os threads.Segmentos podem ser suspenso por sendo feitas para esperar um evento de sincronização é unsignaled e podem ser ativados por alterando o evento estado sinalizado.Se um thread tentar esperar um evento já está sinalizado, em seguida, o thread continuará a ser executado sem atraso.

Há dois tipos de eventos de sincronização: AutoResetEvent e ManualResetEvent.Eles diferem apenas em que AutoResetEvent alterações de sinalizado como unsignaled automaticamente qualquer time ele ativa um thread. Por outro lado, um ManualResetEvent permite que qualquer número de segmentos para ser ativado por estado signaled e só será revertido para um unsignaled estado quando seu Reset método é chamado.

Segmentos podem ser feitos para esperar por eventos, chamando um dos métodos de espera, sistema autônomo WaitOne, WaitAny, ou WaitAll. WaitHandle.WaitOne() faz com que o thread a esperar até que um único evento se torna sinalizado, WaitHandle.WaitAny() bloqueia um thread até que um ou mais eventos indicados tornam-se sinalizado, e WaitHandle.WaitAll() bloqueia o segmento até que todos os eventos indicados tornam-se signaled. Um evento se torna sinalizado quando sua Set método é chamado.

No exemplo a seguir, um thread é criado e iniciado pelo Main função. O novo thread aguarda um evento usando o WaitOne método. A thread está suspensa até que o evento torna-se sinalizado pelo thread principal que está executando o Main função. Depois que o evento torna-se sinalizado, retorna o thread auxiliar.Nesse caso, porque o evento só é usado para ativação de um thread, ambos o AutoResetEvent ou ManualResetEvent classes poderiam ser usadas.

using System;
using System.Threading;

class ThreadingExample
{
    static AutoResetEvent autoEvent;

    static void DoWork()
    {
        Console.WriteLine("   worker thread started, now waiting on event...");
        autoEvent.WaitOne();
        Console.WriteLine("   worker thread reactivated, now exiting...");
    }

    static void Main()
    {
        autoEvent = new AutoResetEvent(false);

        Console.WriteLine("main thread starting worker thread...");
        Thread t = new Thread(DoWork);
        t.Start();

        Console.WriteLine("main thread sleeping for 1 second...");
        Thread.Sleep(1000);

        Console.WriteLine("main thread signaling worker thread...");
        autoEvent.Set();
    }
}

Para obter mais exemplos de sincronização de segmentos evento uso, consulte:

Objetos mutex

A mutex é semelhante a um monitor; ele impede a execução simultânea de um bloco de código por mais de um segmento em um time.Na verdade, o nome "mutex" é uma forma abreviada do termo "mutuamente exclusivo." Ao contrário dos monitores, no entanto, um mutex pode ser usado para sincronizar segmentos entre processos.Um mutex é representado pelo Mutex classe.

Quando usada para sincronização entre processos, um mutex é denominado um mutex nomeado porque está a ser usado em outro aplicativo e, portanto, não pode ser compartilhado por meio de uma variável global ou estática.Ele deve ser fornecido um nome para que ambos os aplicativos possam acessar o mesmo objeto mutex.

Embora um mutex possa ser usado para a sincronização de thread intra-processo, usando Monitor é geralmente preferido, pois monitores foram projetados especificamente para o .NET estrutura e, portanto, fazem melhor uso de recursos. Em contraste, a Mutex classe é um wrapper para uma construção do Win32. Embora seja mais eficiente do que um monitor, um mutex requer transições de interoperabilidade que são mais computacionalmente caros do que aqueles necessários para o Monitor classe. Para obter um exemplo do uso de um mutex, consulte As ' exclusões mútuas '.

Seções relacionadas

Consulte também

Conceitos

Guia de Programação C#

Referência

Thread

WaitOne

WaitAny

WaitAll

Monitor

Mutex

AutoResetEvent

ManualResetEvent

Interlocked

WaitHandle

Outros recursos

Implementando o modelo de programação assíncrono CLR

APM simplificada com translation from VPE for Csharp

Monitor de deadlocks