Partager via


Procédure pas à pas : adaptation d'un code existant pour l'utilisation de tâches légères

Cette rubrique indique comment adapter du code existant qui utilise l'API Windows pour créer et exécuter un thread de façon à utiliser une tâche légère.

Une tâche légère est une tâche que vous planifiez directement à partir d'un objet concurrency::Scheduler ou concurrency::ScheduleGroup. Les tâches légères sont utiles lorsque vous adaptez du code existant de façon à utiliser les fonctionnalités de planification du runtime d'accès concurrentiel.

Composants requis

Avant de démarrer cette procédure pas à pas, lisez la rubrique Planificateur de tâches (runtime d'accès concurrentiel).

Exemple

Description

L'exemple suivant illustre une utilisation typique de l'API Windows pour créer et exécuter un thread. Cet exemple utilise la fonction CreateThread pour appeler MyThreadFunction sur un thread séparé.

Code

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

Commentaires

Cet exemple génère la sortie suivante.

  

Les étapes suivantes indiquent comment adapter l'exemple de code de façon à utiliser le runtime d'accès concurrentiel pour effectuer la même tâche.

Pour adapter l'exemple de façon à utiliser une tâche légère

  1. Ajoutez une directive #include pour le fichier d'en-tête concrt.h.

    #include <concrt.h>
    
  2. Ajoutez une directive using pour l'espace de noms concurrency.

    using namespace concurrency;
    
  3. Modifiez la déclaration de MyThreadFunction de façon à utiliser la convention d'appel __cdecl et à retourner void.

    void __cdecl MyThreadFunction(LPVOID param);
    
  4. Modifiez la structure MyData de façon à inclure un objet concurrency::event qui signale à l'application principale que la tâche est terminée.

    typedef struct MyData {
        int val1;
        int val2;
        event signal;
    } MYDATA, *PMYDATA;
    
  5. Remplacez l'appel à CreateThread par un appel à la méthode concurrency::CurrentScheduler::ScheduleTask.

    CurrentScheduler::ScheduleTask(MyThreadFunction, pData);
    
  6. Remplacez l'appel à WaitForSingleObject par un appel à la méthode concurrency::event::wait pour attendre que la tâche se termine.

    // Wait for the task to finish.
    pData->signal.wait();
    
  7. Supprimez l'appel à CloseHandle.

  8. Modifiez la signature de la définition de MyThreadFunction de sorte qu'elle corresponde à l'étape 3.

    void __cdecl MyThreadFunction(LPVOID lpParam)
    
  9. À la fin de la fonction MyThreadFunction, appelez la méthode concurrency::event::set pour signaler à l'application principale que la tâche est terminée.

    pData->signal.set();
    
  10. Supprimez l'instruction return de MyThreadFunction.

Exemple

Description

L'exemple complet suivant montre du code qui utilise une tâche légère pour appeler la fonction MyThreadFunction.

Code

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

Voir aussi

Référence

Scheduler, classe

Concepts

Planificateur de tâches (runtime d'accès concurrentiel)