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.

Eine einfache Aufgabe ist eine Aufgabe, die Sie direkt von einem Concurrency::Scheduler-Objekt oder einem Concurrency::ScheduleGroup-Objekt planen. Einfache Aufgaben sind nützlich, wenn Sie vorhandenen Code anpassen, um die Planungsfunktionalität der Concurrency Runtime zu verwenden.

Vorbereitungsmaßnahmen

Bevor Sie mit dieser exemplarische Vorgehensweise beginnen, lesen Sie das Thema Taskplaner (Concurrency Runtime).

Beispiel

Beschreibung

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 in einem separaten Thread aufzurufen.

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

Kommentare

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-Direktive für die Headerdatei concrt.h hinzu.

    #include <concrt.h>
    
  2. Fügen Sie eine using-Direktive für den Concurrency-Namespace hinzu.

    using namespace Concurrency;
    
  3. Ändern Sie die Deklaration von MyThreadFunction so, dass die __cdecl-Aufrufkonvention verwendet und void zurückgegeben wird.

    void __cdecl MyThreadFunction(LPVOID param);
    
  4. Ändern Sie die MyData-Struktur so, dass ein Concurrency::event-Objekt eingeschlossen wird, das der Hauptanwendung den Abschluss der Aufgabe signalisiert.

    typedef struct MyData {
        int val1;
        int val2;
        event signal;
    } MYDATA, *PMYDATA;
    
  5. Ersetzen Sie den Aufruf von CreateThread durch einen Aufruf der Concurrency::CurrentScheduler::ScheduleTask-Methode.

    CurrentScheduler::ScheduleTask(MyThreadFunction, pData);
    
  6. Ersetzen Sie den Aufruf von WaitForSingleObject durch einen Aufruf der Concurrency::event::wait-Methode, um auf den Abschluss der Aufgabe zu warten.

    // Wait for the task to finish.
    pData->signal.wait();
    
  7. Entfernen Sie den Aufruf von CloseHandle.

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

    void __cdecl MyThreadFunction(LPVOID lpParam)
    
  9. Rufen Sie am Ende der MyThreadFunction-Funktion die Concurrency::event::set-Methode auf, um der Hauptanwendung den Abschluss der Aufgabe zu signalisieren.

    pData->signal.set();
    
  10. Entfernen Sie die return-Anweisung von MyThreadFunction.

Beispiel

Beschreibung

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

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

Siehe auch

Referenz

Scheduler-Klasse

Konzepte

Taskplaner (Concurrency Runtime)