you can get all threads of your application by code, I found this feature is useful, when some thread runs an infinite loop by mistake:)
BOOL CThreadList::Update(DWORD dwProcessID, BOOL bGetContext)
{
HANDLE hThreadSnap = NULL;
BOOL bRet = FALSE;
THREAD_INFORMATION_EX tie;
DWORD dwThisThread = ::GetCurrentThreadId(); // used for not killing ourself
// Take a snapshot of all threads currently in the system.
hThreadSnap = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, dwProcessID);
if (hThreadSnap == INVALID_HANDLE_VALUE)
return FALSE;
// Fill in the size of the structure before using it.
tie.te32.dwSize = sizeof(THREADENTRY32);
// Walk the thread snapshot to find all threads of the process.
// If the thread belongs to the process, add its information
// to the display list.
if (Thread32First(hThreadSnap, &tie.te32))
{
do
{
//
// if the thread belongs to the given process...
//
if (tie.te32.th32OwnerProcessID == dwProcessID)
{
if(bGetContext && (dwThisThread != tie.te32.th32ThreadID))
{
//
// get some more information about this thread
//
HANDLE hThread = ::OpenThread(THREAD_GET_CONTEXT|THREAD_QUERY_INFORMATION, FALSE, tie.te32.th32ThreadID);
if(hThread != INVALID_HANDLE_VALUE)
{
::SuspendThread(hThread); // otherwise we dont get the context
{
tie.ctx.ContextFlags = CONTEXT_FULL;
::GetThreadContext(hThread, &tie.ctx);
}
::ResumeThread(hThread);
::CloseHandle(hThread);
}
}
#ifdef _VERBOSE_DEBUG
TRACE( "\nTID\t\t%d (@%i)\n", tie.te32.th32ThreadID, tie.te32.th32OwnerProcessID);
TRACE( "Base Priority\t%d\n", tie.te32.tpBasePri);
if(tie.ctx.ContextFlags)
{
TRACE("EIP\t\t0x%08x\n", tie.ctx.Eip);
TRACE("ESP\t\t0x%08x\n", tie.ctx.Esp);
}
#endif
#if defined(USE_STL)
push_back(tie);
#else
Add(tie);
#endif
ZeroMemory(&tie, sizeof(THREAD_INFORMATION_EX));
tie.te32.dwSize = sizeof(THREADENTRY32);
}
}
while (Thread32Next(hThreadSnap, &tie.te32));
bRet = TRUE;
}
else
bRet = FALSE; // could not walk the list of threads