Compartilhar via


Instruções passo a passo: adaptando um código existente para usar tarefas leves

Este tópico mostra como adaptar o código que usa a API do Windows para criar e executar um thread para usar uma tarefa leve.

Uma tarefa leve é uma tarefa que você agenda diretamente de um objeto concurrency::Scheduler ou concurrency::ScheduleGroup. Tarefas leves são úteis quando você adapta o código existente para usar a funcionalidade de agendamento do Runtime de Simultaneidade.

Pré-requisitos

Antes de iniciar este guia passo a passo, leia o tópico Agendador de Tarefas.

Exemplo

O exemplo a seguir ilustra o uso típico da API do Windows para criar e executar um thread. Este exemplo usa a função CreateThread para chamar um thread MyThreadFunction separado.

Código inicial

// windows-threads.cpp
#include <windows.h>
#include <tchar.h>
#include <strsafe.h>

#define BUF_SIZE 255

DWORD WINAPI MyThreadFunction(LPVOID param);

// Data structure for threads to use.
typedef struct MyData {
    int val1;
    int val2;
} MYDATA, *PMYDATA;

int _tmain()
{
   // Allocate memory for thread data.
   PMYDATA pData = (PMYDATA) HeapAlloc(GetProcessHeap(), 
      HEAP_ZERO_MEMORY, sizeof(MYDATA));

   if( pData == NULL )
   {
      ExitProcess(2);
   }

   // Set the values of the thread data.
   pData->val1 = 50;
   pData->val2 = 100;

   // Create the thread to begin execution on its own.
   DWORD dwThreadId;
   HANDLE hThread = CreateThread( 
      NULL,                   // default security attributes
      0,                      // use default stack size  
      MyThreadFunction,       // thread function name
      pData,                  // argument to thread function 
      0,                      // use default creation flags 
      &dwThreadId);           // returns the thread identifier 

   if (hThread == NULL) 
   {      
      ExitProcess(3);
   }

   // Wait for the thread to finish.
   WaitForSingleObject(hThread, INFINITE);

   // Close the thread handle and free memory allocation.
   CloseHandle(hThread);
   HeapFree(GetProcessHeap(), 0, pData);

   return 0;
}

DWORD WINAPI MyThreadFunction(LPVOID lpParam)
{
   PMYDATA pData = (PMYDATA)lpParam;

   // Use thread-safe functions to print the parameter values.

   TCHAR msgBuf[BUF_SIZE];
   StringCchPrintf(msgBuf, BUF_SIZE, TEXT("Parameters = %d, %d\n"), 
     pData->val1, pData->val2); 

   size_t cchStringSize;
   StringCchLength(msgBuf, BUF_SIZE, &cchStringSize);

   DWORD dwChars;
   WriteConsole(GetStdHandle(STD_OUTPUT_HANDLE), msgBuf, (DWORD)cchStringSize, &dwChars, NULL);

   return 0;
}

Este exemplo gerencia a seguinte saída.

Parameters = 50, 100

As etapas a seguir mostram como adaptar o exemplo de código para usar o Runtime de Simultaneidade para executar a mesma tarefa.

Para adaptar o exemplo a fim de usar uma tarefa leve

  1. Adicione uma diretiva #include ao arquivo de cabeçalho concrt.h.
#include <concrt.h>
  1. Adicione uma diretiva using para o namespace concurrency.
using namespace concurrency;
  1. Altere a declaração de MyThreadFunction para usar a convenção de chamada __cdecl e retornar void.
void __cdecl MyThreadFunction(LPVOID param);
  1. Modifique a estrutura MyData para incluir um objeto concurrency::event que sinaliza para o aplicativo principal que a tarefa terminou.
typedef struct MyData {
    int val1;
    int val2;
    event signal;
} MYDATA, *PMYDATA;
  1. Substitua a chamada a CreateThread por uma chamada para o método concurrency::CurrentScheduler::ScheduleTask.
CurrentScheduler::ScheduleTask(MyThreadFunction, pData);
  1. Substitua a chamada a WaitForSingleObject por uma chamada ao método concurrency::event::wait para aguardar a conclusão da tarefa.
// Wait for the task to finish.
pData->signal.wait();
  1. Remova a chamada para CloseHandle.

  2. Altere a assinatura da definição de MyThreadFunction para que corresponda à etapa 3.

void __cdecl MyThreadFunction(LPVOID lpParam)
  1. No final da função MyThreadFunction, chame o método concurrency::event::set para sinalizar para o aplicativo principal que a tarefa terminou.
pData->signal.set();
  1. Remova a instrução return de MyThreadFunction.

Código concluído

O exemplo concluído a seguir mostra o código que usa uma tarefa leve para chamar a função MyThreadFunction.

// migration-lwt.cpp
// compile with: /EHsc
#include <windows.h>
#include <tchar.h>
#include <strsafe.h>
#include <concrt.h>

using namespace concurrency;

#define BUF_SIZE 255

void __cdecl MyThreadFunction(LPVOID param);

// Data structure for threads to use.
typedef struct MyData {
    int val1;
    int val2;
    event signal;
} MYDATA, *PMYDATA;

int _tmain()
{
   // Allocate memory for thread data.
   PMYDATA pData = (PMYDATA) HeapAlloc(GetProcessHeap(), 
      HEAP_ZERO_MEMORY, sizeof(MYDATA));

   if( pData == NULL )
   {
      ExitProcess(2);
   }

   // Set the values of the thread data.
   pData->val1 = 50;
   pData->val2 = 100;

   // Create the thread to begin execution on its own.
   CurrentScheduler::ScheduleTask(MyThreadFunction, pData);

   // Wait for the task to finish.
   pData->signal.wait();

   // Free memory allocation.
   HeapFree(GetProcessHeap(), 0, pData);

   return 0;
}

void __cdecl MyThreadFunction(LPVOID lpParam)
{
   PMYDATA pData = (PMYDATA)lpParam;

   // Use thread-safe functions to print the parameter values.

   TCHAR msgBuf[BUF_SIZE];
   StringCchPrintf(msgBuf, BUF_SIZE, TEXT("Parameters = %d, %d\n"), 
     pData->val1, pData->val2); 

   size_t cchStringSize;
   StringCchLength(msgBuf, BUF_SIZE, &cchStringSize);

   DWORD dwChars;
   WriteConsole(GetStdHandle(STD_OUTPUT_HANDLE), msgBuf, (DWORD)cchStringSize, &dwChars, NULL);

   pData->signal.set();
}

Confira também

Agendador de Tarefas
Classe Scheduler