Condividi tramite


Procedura dettagliata: Adattamento del codice esistente per l'uso di attività leggere

Questo argomento illustra come adattare il codice esistente che usa l'API di Windows per creare ed eseguire un thread per usare un'attività leggera.

Un'attività leggera è un'attività pianificata direttamente da un oggetto concurrency::Scheduler o concurrency::ScheduleGroup . Le attività leggere sono utili quando si adatta il codice esistente per usare la funzionalità di pianificazione del runtime di concorrenza.

Prerequisiti

Prima di iniziare questa procedura dettagliata, leggere l'argomento Utilità di pianificazione.

Esempio

L'esempio seguente illustra l'utilizzo tipico dell'API Windows per creare ed eseguire un thread. In questo esempio viene utilizzata la funzione CreateThread per chiamare su MyThreadFunction un thread separato.

Codice iniziale

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

Questo esempio produce il seguente output:

Parameters = 50, 100

I passaggi seguenti illustrano come adattare l'esempio di codice per usare il runtime di concorrenza per eseguire la stessa attività.

Per adattare l'esempio all'uso di un'attività leggera

  1. Aggiungere una #include direttiva per il file di intestazione concrt.h.
#include <concrt.h>
  1. Aggiungere una using direttiva per lo spazio dei concurrency nomi .
using namespace concurrency;
  1. Modificare la dichiarazione di per usare la __cdecl convenzione di MyThreadFunction chiamata e restituire void.
void __cdecl MyThreadFunction(LPVOID param);
  1. Modificare la MyData struttura in modo da includere un oggetto concurrency::event che segnala all'applicazione principale che l'attività è stata completata.
typedef struct MyData {
    int val1;
    int val2;
    event signal;
} MYDATA, *PMYDATA;
  1. Sostituire la chiamata a CreateThread con una chiamata al metodo concurrency::CurrentScheduler::ScheduleTask .
CurrentScheduler::ScheduleTask(MyThreadFunction, pData);
  1. Sostituire la chiamata a WaitForSingleObject con una chiamata al metodo concurrency::event::wait per attendere il completamento dell'attività.
// Wait for the task to finish.
pData->signal.wait();
  1. Rimuovere la chiamata a CloseHandle.

  2. Modificare la firma della definizione di MyThreadFunction in modo che corrisponda al passaggio 3.

void __cdecl MyThreadFunction(LPVOID lpParam)
  1. Alla fine della MyThreadFunction funzione chiamare il metodo concurrency::event::set per segnalare all'applicazione principale che l'attività è stata completata.
pData->signal.set();
  1. Rimuovere l'istruzione return da MyThreadFunction.

Codice completato

L'esempio seguente illustra il codice che usa un'attività leggera per chiamare la MyThreadFunction funzione.

// 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();
}

Vedi anche

Utilità di pianificazione
Classe Scheduler