Jak używać CreateThread()
do tworzenia wątków funkcji, które są członkami klasy?W jaki sposób używasz CreateThread do funkcji, które są członkami klasy?
36
A
Odpowiedz
62
Należy utworzyć statyczną metodę do użycia jako rzeczywistą funkcję startową wątku i przekazać wskaźnik do instancji jako argument lpParameter
do CreateThread
. To zostanie przekazane do metody statycznej, która może rzucić ją do wskaźnika obiektu i wywołać funkcję członka.
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
Inni, z którymi można się spotkać, mogą chcieć skorzystać z mojego rozwiązania. Jest to kompletny plik źródłowy skompilowany z VS2008. Poniżej znajduje się krótki przykład instrukcji użycia!
// 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__
Krótki przykład:
// 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;
}
Powiązane problemy
- 1. W jaki sposób używasz MediaControllerCompat do sterowania bieżącym odtwarzaczem?
- 2. W jaki sposób można użyć enable_if do wzajemnie wykluczających się szablonów funkcji nie będących członkami?
- 3. Jaki jest cel parametrów javascript, które są nadpisywane w funkcji?
- 4. W jaki sposób używasz wyrażeń C# Lambda?
- 5. Jak uzyskać zadanie, które korzysta z Kontakty synchronizacji? A w jaki sposób używasz SynchronizationContext?
- 6. W jaki sposób sprawdzić poprawność funkcji, które używają losowo?
- 7. W jaki sposób używasz preprocesora do tworzenia biblioteki wieloplatformowej?
- 8. W jaki sposób używasz wtrysku sprężyny do testowania jednostki kontrolera?
- 9. W jaki sposób Chocolatey wie, które pakiety są zainstalowane lokalnie?
- 10. W jaki sposób używasz innego niż domyślny konstruktora dla członka?
- 11. W jaki sposób używasz pliku Machine.config, czy też?
- 12. Zastosowanie CreateThread z lambda
- 13. iteracja nad członkami danych klasy case
- 14. W jaki sposób używasz dosłownych łańcuchów z interpolacją?
- 15. w jaki sposób używasz menedżerów subskrypcji z subskrypcjami szablonów meteorów?
- 16. W jaki sposób są analizowane szablony Django?
- 17. Gdzie używasz generatorów funkcji w kodzie Pythona?
- 18. W jaki sposób przetwarzane są `: ~ @` i `:! @`?
- 19. W jaki sposób Python zapobiega podklasie klasy?
- 20. CreateThread vs fork()
- 21. W jaki sposób realizowane są generatory i coroutines w CPython?
- 22. W jaki sposób mogę testować funkcje urządzenia Perl, które są drukowane na ekranie?
- 23. W jaki sposób używasz Wyrażeń regularnych do zamiany określonego dopasowania (np. "Ostatni" lub "drugi do ostatniego")?
- 24. W jaki sposób sygnał i gniazda są zaimplementowane pod maską?
- 25. W jaki sposób pliki .apk są podpisywane?
- 26. W jaki sposób reprezentowane są jednostki miary?
- 27. W jaki sposób wybierane są rozmiary buforów?
- 28. W jaki sposób mogę automatycznie aktualizować import funkcji funkcji jednostki
- 29. W jaki sposób są rozwiązywane symbole zewnętrzne?
- 30. W jaki sposób DexGuard szyfruje klasy?