クラスの 1 つのコンストラクターで、CreateThread
最後の操作として Windows 関数を呼び出します。すぐに実行するスレッドが作成され、クラスの this ポインターを として渡しますlpParameter
。
スレッド プロシージャで、渡されたパラメーターをクラスのポインターにキャストし、名前を付けますpThis
。
を呼び出したときに渡したポインタと同じメモリ位置pThis
を指していることがわかります。ただし、アクセスされるメンバー変数を見ると、それらはすべて間違った値を持っています。this
CreateThread
pThis->...
this->member_variable
this ポインターが属するクラスの usedの値はpThis->member_variable
、スレッドのプロシージャーに記述したときに取得する値と同じであると予想していました。
CreateThread
別のメンバー関数 (コンストラクターではない)を呼び出すと、すべてが正しく動作します。
したがって、質問: CreateThread
C++ クラスのコンストラクター内から Windows 関数を呼び出すことは禁止されていますか? はいの場合、何が問題ですか?
説明:
1) オブジェクトが常に存在することを確認できます。オブジェクトは、プログラム全体が終了したときにのみスコープから外れます。既に述べたようにCreateThread
、他のメンバー関数からの呼び出しは機能します。
2) 「有線」の誤字を修正しました。「変」だったはずです。申し訳ありません。
いくつかのコード:
「欠陥のある」部分を維持しながら、物事を最小限に減らすコードスニペットを投稿しようとしています。
class CTimerW32 : public CTimer
{
public:
CTimerW32();
~CTimerW32();
private:
static void CALLBACK TimerCallback(LPVOID lpParam, BOOLEAN bReason);
static DWORD WINAPI WaitCompletition(LPVOID lpParam);
private:
HANDLE m_hCompletitionEvent;
HANDLE m_hCompletitionThread;
bool m_bStartDeferred;
};
CTimer
基本クラスは、さまざまなプラットフォームでのビルドを可能にする単なる抽象基本クラスであるため、安全に無視できます。
CTimerW32::CTimerW32()
{
m_bStartDeferred= false;
m_hCompletitionEvent= CreateEvent(NULL, FALSE, FALSE, NULL);
m_hCompletitionThread= CreateThread(NULL, 0, WaitCompletition, this, 0, NULL);
}
m_hCompletitionEvent
ここで、 への呼び出し後に有効であることがわかりますCreateEvent
。
DWORD WINAPI CTimerW32::WaitCompletition(LPVOID lpParam)
{
CTimerW32* pThis;
DWORD dwRet;
pThis= (CTimerW32*)(lpParam);
while (true) {
// just wait for the completition event to be signaled
dwRet= WaitForSingleObject(pThis->m_hCompletitionEvent, INFINITE);
// ...
if (pThis->m_bStartDeferred) {
// ...
}
}
ここで、 への呼び出しで問題が発生していますWaitForSingleObject
。既に述べたように、クラスCTimerW32
(現在pThis
) のオブジェクトの this ポインターは、スレッドの作成時に this ポインターと同じ値を保持しています。ただし、ハンドルはpThis->m_hCompletitionEvent
ランダム データのようです。CreateEvent
コンストラクターでの呼び出し後に観察される値ではありません。