Exemplarische Vorgehensweise: Anpassen von vorhandenem Code für die Verwendung einfacher Aufgaben

In diesem Thema wird erläutert, wie vorhandener Code, der die Windows-API verwendet, zum Erstellen und Ausführen eines Threads für die Ausführung einer einfachen Aufgabe angepasst wird.

Ein einfacher Vorgang ist ein Vorgang , den Sie direkt aus einem Parallelitätsobjekt::Scheduler oder Parallelität::ScheduleGroup-Objekt planen. Einfache Aufgaben sind nützlich, wenn Sie vorhandenen Code anpassen, um die Planungsfunktionalität der Concurrency Runtime zu verwenden.

Voraussetzungen

Bevor Sie mit dieser exemplarischen Vorgehensweise beginnen, lesen Sie das Thema "Vorgangsplaner".

Beispiel

Das folgende Beispiel veranschaulicht die typische Verwendung der Windows-API zum Erstellen und Ausführen eines Threads. In diesem Beispiel wird die CreateThread-Funktion verwendet, um die MyThreadFunction Funktion in einem separaten Thread aufzurufen.

Anfangscode

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

Folgende Ergebnisse werden zurückgegeben:

Parameters = 50, 100

Die folgenden Schritte geben an, wie das Codebeispiel angepasst wird, um die Concurrency Runtime zum Durchführen der gleichen Aufgabe zu verwenden.

So passen Sie das Beispiel an, um eine einfache Aufgabe zu verwenden

  1. Fügen Sie eine #include-Anweisung für die Headerdatei concrt.h hinzu.
#include <concrt.h>
  1. Fügen Sie eine using-Direktive für den concurrency-Namespace hinzu.
using namespace concurrency;
  1. Ändern Sie die Deklaration von MyThreadFunction so, dass die __cdecl-Aufrufkonvention verwendet und void zurückgegeben wird.
void __cdecl MyThreadFunction(LPVOID param);
  1. Ändern Sie die MyData Struktur so, dass sie ein Parallelitätsobjekt::event enthält, das der Standard Anwendung signalisiert, die die Aufgabe abgeschlossen hat.
typedef struct MyData {
    int val1;
    int val2;
    event signal;
} MYDATA, *PMYDATA;
  1. Ersetzen Sie den Aufruf durch einen Aufruf CreateThread der Parallelität::CurrentScheduler::ScheduleTask-Methode .
CurrentScheduler::ScheduleTask(MyThreadFunction, pData);
  1. Ersetzen Sie den Aufruf durch einen Aufruf WaitForSingleObject der Parallelität::event::wait-Methode , um zu warten, bis die Aufgabe abgeschlossen ist.
// Wait for the task to finish.
pData->signal.wait();
  1. Entfernen Sie den Aufruf von CloseHandle.

  2. Ändern Sie die Signatur der Definition von MyThreadFunction so, dass sie Schritt 3 entspricht.

void __cdecl MyThreadFunction(LPVOID lpParam)
  1. Rufen Sie am Ende der MyThreadFunction Funktion die Parallelität::event::set-Methode auf, um der Standard Anwendung zu signalisieren, dass die Aufgabe abgeschlossen ist.
pData->signal.set();
  1. Entfernen Sie die return-Anweisung von MyThreadFunction.

Abgeschlossener Code

Im folgenden vollständigen Beispiel wird eine einfache Aufgabe verwendet, um die MyThreadFunction-Funktion aufzurufen.

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

Siehe auch

Aufgabenplanung
Scheduler-Klasse