Condividi tramite


Procedura dettagliata: adattamento del codice esistente per l'utilizzo delle attività leggere

In questo argomento viene illustrato come adattare il codice esistente che utilizza l'API Windows per creare ed eseguire un thread per utilizzare un'attività leggera.

Per attività leggera si intende un'attività che si pianifica direttamente da un oggetto Concurrency::Scheduler o Concurrency::ScheduleGroup. Le attività leggere sono utili quando si adatta il codice esistente per utilizzare la funzionalità di pianificazione del runtime di concorrenza.

Prerequisiti

Prima di iniziare questa procedura dettagliata, leggere l'argomento Utilità di pianificazione (runtime di concorrenza).

Esempio

Descrizione

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

Codice

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

Commenti

Questo esempio produce l'output che segue.

Parameters = 50, 100

Nei passaggi seguenti viene illustrato come adattare l'esempio di codice per l'utilizzo del runtime di concorrenza per eseguire la stessa attività.

Per adattare l'esempio per l'utilizzo di un'attività leggera

  1. Aggiungere una direttiva #include per file di intestazione concrt.h.

    #include <concrt.h>
    
  2. Aggiungere una direttiva using per lo spazio dei nomi Concurrency.

    using namespace Concurrency;
    
  3. Modificare la dichiarazione di MyThreadFunction in modo da utilizzare la convenzione di chiamata __cdecl e restituire void.

    void __cdecl MyThreadFunction(LPVOID param);
    
  4. Modificare la struttura MyData in modo da includere un oggetto Concurrency::event che segnali all'applicazione principale il completamento dell'attività.

    typedef struct MyData {
        int val1;
        int val2;
        event signal;
    } MYDATA, *PMYDATA;
    
  5. Sostituire la chiamata a CreateThread con una chiamata al metodo Concurrency::CurrentScheduler::ScheduleTask.

    CurrentScheduler::ScheduleTask(MyThreadFunction, pData);
    
  6. 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();
    
  7. Rimuovere la chiamata a CloseHandle.

  8. Modificare la firma della definizione di MyThreadFunction in modo da corrispondere al passaggio 3.

    void __cdecl MyThreadFunction(LPVOID lpParam)
    
  9. Al termina della funzione MyThreadFunction, chiamare il metodo Concurrency::event::set per segnalare all'applicazione principale il completamento dell'attività.

    pData->signal.set();
    
  10. Rimuovere l'istruzione return da MyThreadFunction.

Esempio

Descrizione

Nell'esempio completato seguente viene illustrato il codice che utilizza un'attività leggera per chiamare la funzione MyThreadFunction.

Codice

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

Vedere anche

Riferimenti

Classe Scheduler

Concetti

Utilità di pianificazione (runtime di concorrenza)