E/S de pipe síncrono e sobreposto

As funções ReadFile, WriteFile, TransactNamedPipe e ConnectNamedPipe podem executar operações de entrada e saída em um pipe de forma síncrona ou assíncrona. Quando uma função é executada de forma síncrona, ela não retorna até que a operação que está sendo executada seja concluída. Isso significa que a execução do thread de chamada pode ser bloqueada por um período indefinido enquanto aguarda a conclusão de uma operação demorada. Quando uma função é executada de forma assíncrona, ela retorna imediatamente, mesmo que a operação não tenha sido concluída. Isso permite que uma operação demorada seja executada em segundo plano enquanto o thread de chamada é livre para executar outras tarefas.

O uso de E/S assíncrona permite que um servidor de pipe use um loop que execute as seguintes etapas:

  1. Especifique vários objetos de evento em uma chamada para a função de espera e aguarde até que um dos objetos seja definido como o estado sinalizado.
  2. Use o valor retornado da função de espera para determinar qual operação sobreposta foi concluída.
  3. Execute as tarefas necessárias para limpo a operação concluída e iniciar a próxima operação para esse identificador de pipe. Isso pode envolver a inicialização de outra operação sobreposta para o mesmo identificador de pipe.

As operações sobrepostas possibilitam que um pipe leia e escreva dados simultaneamente e que um único thread execute operações simultâneas de E/S em várias alças de pipe. Isso permite que um servidor de pipe de thread único manipule as comunicações com vários clientes de pipe com eficiência. Para obter um exemplo, consulte Servidor de pipe nomeado usando E/S sobreposta.

Para que um servidor de pipe use operações síncronas para se comunicar com mais de um cliente, ele deve criar um thread separado para cada cliente de pipe para que um ou mais threads possam ser executados enquanto outros threads estão aguardando. Para obter um exemplo de um servidor de pipe multithread que usa operações síncronas, consulte Servidor de Pipe Multithreaded.

Habilitando a operação assíncrona

As funções ReadFile, WriteFile, TransactNamedPipe e ConnectNamedPipe só poderão ser executadas de forma assíncrona se você habilitar o modo sobreposto para o identificador de pipe especificado e especificar um ponteiro válido para uma estrutura OVERLAPPED . Se o ponteiro OVERLAPPED for NULL, o valor retornado da função poderá indicar incorretamente que a operação foi concluída. Portanto, é altamente recomendável que, se você criar um identificador com FILE_FLAG_OVERLAPPED e desejar um comportamento assíncrono, sempre especifique uma estrutura OVERLAPPED válida.

O membro hEvent da estrutura OVERLAPPED especificada deve conter um identificador para um objeto de evento de redefinição manual. Esse é um objeto de sincronização criado pela função CreateEvent . O thread que inicia a operação sobreposta usa o objeto de evento para determinar quando a operação foi concluída. Você não deve usar o identificador de pipe para sincronização ao executar operações simultâneas no mesmo identificador porque não há como saber qual conclusão da operação fez com que o identificador de pipe fosse sinalizado. A única técnica confiável para executar operações simultâneas no mesmo identificador de pipe é usar uma estrutura OVERLAPPED separada com seu próprio objeto de evento para cada operação. Para obter mais informações sobre objetos de evento, consulte Sincronização.

Além disso, você pode ser notificado quando uma operação sobreposta for concluída usando as funções GetQueuedCompletionStatus ou GetQueuedCompletionStatusEx . Nesse caso, você não precisa atribuir o evento de redefinição manual na estrutura OVERLAPPED e a conclusão ocorre no identificador de pipe da mesma forma que uma operação assíncrona de leitura ou gravação. Para obter mais informações, consulte Portas de conclusão de E/S.

Quando as operações ReadFile, WriteFile, TransactNamedPipe e ConnectNamedPipe são executadas de forma assíncrona, ocorre um destes procedimentos:

  • Se a operação for concluída quando a função retornar, o valor retornado indicará o êxito ou a falha da operação. Se ocorrer um erro, o valor retornado será zero e a função GetLastError retornará algo diferente de ERROR_IO_PENDING.
  • Se a operação não tiver sido concluída quando a função retornar, o valor retornado será zero e GetLastError retornará ERROR_IO_PENDING. Nesse caso, o thread de chamada deve aguardar até que a operação seja concluída. O thread de chamada deve chamar a função GetOverlappedResult para determinar os resultados.

Usando rotinas de conclusão

As funções ReadFileEx e WriteFileEx fornecem outra forma de E/S sobreposta. Ao contrário das funções ReadFile e WriteFile sobrepostas, que usam um objeto de evento para sinalizar a conclusão, as funções estendidas especificam uma rotina de conclusão. Uma rotina de conclusão é uma função que é enfileirada para execução quando a operação de leitura ou gravação é concluída. A rotina de conclusão não é executada até que o thread chamado ReadFileEx e WriteFileEx inicie uma operação de espera alertável chamando uma das funções de espera alertáveis com o parâmetro fAlertable definido como TRUE. Em uma operação de espera alertável, as funções também retornam quando uma rotina de conclusão ReadFileEx ou WriteFileEx é enfileirada para execução. Um servidor de pipe pode usar as funções estendidas para executar uma sequência de operações de leitura e gravação para cada cliente que se conecta a ele. Cada operação de leitura ou gravação na sequência especifica uma rotina de conclusão e cada rotina de conclusão inicia a próxima etapa na sequência. Para obter um exemplo, consulte Servidor de pipe nomeado usando rotinas de conclusão.