Comment utiliser CreateThread()
pour créer des threads de fonctions qui sont des membres de classe?Comment utilisez-vous CreateThread pour les fonctions qui sont membres de la classe?
36
A
Répondre
62
Vous devez créer une méthode statique à utiliser en tant que fonction de démarrage de thread réelle et transmettre un pointeur à l'instance en tant qu'argument lpParameter
à CreateThread
. Cela sera passé à la méthode statique, qui peut le convertir en un pointeur d'objet et appeler jusqu'à la fonction membre.
class MyClass
{
static DWORD WINAPI StaticThreadStart(void* Param)
{
MyClass* This = (MyClass*) Param;
return This->ThreadStart();
}
DWORD ThreadStart(void)
{
// Do stuff
}
void startMyThread()
{
DWORD ThreadID;
CreateThread(NULL, 0, StaticThreadStart, (void*) this, 0, &ThreadID);
}
};
9
Les autres utilisateurs qui souhaitent utiliser ma solution peuvent le faire. C'est un fichier source complet compilé avec VS2008. Voir ci-dessous pour un court exemple d'instruction sur la façon d'utiliser!
// Thread.h
#ifndef __THREAD_H__
#define __THREAD_H__
// #############################################################################
#define WIN32_LEAN_AND_MEAN
#include <Windows.h>
// =============================================================================
template<class T>
class Thread
{
// new type Method: pointer to a object's method (this call)
typedef DWORD (T::* Method)(void);
// -----------------------------------------------------------------------------
protected:
HANDLE hThread; // unique handle to the thread
private:
DWORD threadID; // thread id - 0 until started
T* object; // the object which owns the method
Method method; // the method of the object
HANDLE hInterrupt; // mutex to signal an interrupt via ReleaseSemaphore()
HANDLE hSingleStart; // only one thread allowed to call start() mutex
// -----------------------------------------------------------------------------
private:
// This function gets executed by a concurrent thread.
static DWORD run(LPVOID thread_obj)
{
Thread<T>* thread = (Thread<T>*)thread_obj;
return (thread->object->*thread->method)();
}
// Prevent copying of threads: No sensible implementation!
Thread(const Thread<T>& other) {}
// Prevent assignment of threads: No sensible implementation!
Thread<T>& operator =(const Thread<T>& other) {}
// -----------------------------------------------------------------------------
public:
/* Creates a new Thread object. object: the one which method should be
executed. method: pointer to the object's method. */
explicit Thread(T* object, DWORD (T::* method)(void))
{
this->hThread = NULL;
this->object = object;
this->method = method;
this->threadID = 0;
this->hInterrupt = CreateSemaphore(NULL, 1, 1, NULL);
this->hSingleStart = CreateMutex(NULL, FALSE, NULL);
// this->hInterrupt = CreateMutex(NULL, FALSE, NULL);
}
// -----------------------------------------------------------------------------
~Thread(void)
{
if (hInterrupt)
CloseHandle(hInterrupt);
if (hThread)
CloseHandle(hThread);
}
// -----------------------------------------------------------------------------
/* Starts executing the objects method in a concurrent thread. True if the
thread was started successfully; otherwise false. */
bool start()
{
__try {
if (WaitForSingleObject(hSingleStart, 0) != WAIT_OBJECT_0)
return false;
if (hThread) // Thread had been started sometime in the past
{
if (WaitForSingleObject(hThread, 0) == WAIT_TIMEOUT)
{ // if thread's still running deny new start
return false;
}
CloseHandle(hThread);
}
// (Re-)Set not interrupted semaphore state
WaitForSingleObject(hInterrupt, 0);
hThread = CreateThread(
NULL,
0,
(LPTHREAD_START_ROUTINE) Thread<T>::run,
this,
0,
&this->threadID
);
if (hThread)
return true;
return false;
}
__finally
{
ReleaseMutex(hSingleStart);
}
}
// -----------------------------------------------------------------------------
// Blocks the calling thread until this thread has stopped.
inline void join()
{
WaitForSingleObject(hThread, INFINITE);
}
// -----------------------------------------------------------------------------
/* Asks the thread to exit nicely. Thread function must implement checks.
return value indicates if the interrupt could be placed not if the thread
reacts on the interrupt. true indicates success, false an error. */
inline bool interrupt()
{
if (hInterrupt)
{
return ((ReleaseSemaphore(hInterrupt, 1, NULL) == FALSE) ?
false : true);
}
return false;
}
// -----------------------------------------------------------------------------
/* True if an interrupt request was set, otherwise false. */
inline bool isInterrupted()
{
return this->isInterrupted(0);
}
// -----------------------------------------------------------------------------
/* True if an interrupt request was set, otherwise false. Waits for millisec
milliseconds for the interrupt to take place. */
inline bool isInterrupted(DWORD millisec)
{
if (WaitForSingleObject(hInterrupt, millisec) == WAIT_TIMEOUT)
{
return false;
}
ReleaseSemaphore(hInterrupt, 1, NULL); // keep interrupted state
return true;
}
// -----------------------------------------------------------------------------
inline bool isRunning()
{
DWORD exitCode = 0;
if (hThread)
GetExitCodeThread(hThread, &exitCode);
if (exitCode == STILL_ACTIVE)
return true;
return false;
}
// -----------------------------------------------------------------------------
// Getter & Setter
// -----------------------------------------------------------------------------
__declspec(property(get = getThreadHandle)) HANDLE ThreadHandle;
inline HANDLE getThreadHandle()
{
return hThread;
}
// -----------------------------------------------------------------------------
__declspec(property(get = getThreadID)) DWORD ThreadID;
inline DWORD getThreadID()
{
return threadID;
}
// -----------------------------------------------------------------------------
};
// #############################################################################
#endif // __THREAD_H__
exemple court:
// main.cpp
#include <iostream>
#include <string>
#include "Thread.h"
class HelloWorld
{
public:
DWORD print()
{
std::cout << "Hello World!" << std::endl;
return 0;
}
};
int main(void)
{
// Random object with DWORD method (void)
HelloWorld world;
// thread should call print method of world.
Thread<HelloWorld> thread(&world, &HelloWorld::print);
if (thread.start())
std::cout << "Thread start()" << std::endl;
thread.join(); // wait for thread
return 0;
}
Questions connexes
- 1. spécialisation de modèle pour les fonctions membres statiques; comment?
- 2. Comment trouver les fonctions qui ne sont pas exécutées?
- 3. Fonctions membres C++ vs fonctions libres
- 4. Logiciel pour regrouper les membres de la classe C#
- 5. Fonctions de test unitaires qui ne modifient que les variables membres privées
- 6. Attributs personnalisés sur les membres de la classe
- 7. Les membres de classe dérivés ne sont pas disponibles lorsqu'ils sont ajoutés à la base de collecte personnalisée
- 8. Quelle est la meilleure utilisation que vous avez faite du pointeur vers les membres et les fonctions membres?
- 9. Déclarer les variables membres avec la classe gen dans Clojure
- 10. Xmlserializer ne sérialisant pas les membres de classe de base
- 11. Exécuter du code spécifique avant les fonctions membres d'une classe utilisant des attributs?
- 12. C++ - quand les membres de classe non-pointers sont-ils détruits?
- 13. symbole externe non résolu sur les membres de la classe statique
- 14. Pourquoi PHP requiert-il une référence explicite à "$ this" pour appeler les fonctions membres?
- 15. Verrouillage des membres de la classe dans PHP
- 16. Comportement virtuel en stockant des pointeurs sur les fonctions membres
- 17. Problème d'accès des membres de classe C++ avec les modèles
- 18. Modèle de conception pour les fonctions optionnelles?
- 19. Membres de classe ambigus dans vb.net
- 20. Comment exclure certains classe/paquets/membres publics de javadoc
- 21. C# Héritage, accès aux membres enfants avec les fonctions de base?
- 22. itérateur pour remplacer les membres de la liste en Java?
- 23. Résumé Membres de la classe de base et des données? Comment ça marche?
- 24. Meilleure pratique pour initialiser les variables membres?
- 25. In Héritage: Puis-je remplacer les membres de données de la classe de base?
- 26. Deadlocks avec pthreads et CreateThread
- 27. Comment identifier les membres abstraits par réflexion
- 28. Pourquoi les fonctions de parenscript sont-elles modifiées en minuscules?
- 29. Quels types de fonctions sont candidats à la mémorisation?
- 30. Que sont les fichiers de fonctions PHP et leurs utilisateurs?