提供好的测试工具和测试思路都行!
5 个解决方案
#1
用CEvent或是CCriticalSection类来加个临界区
#2
在程序运行当中,用windows的任务管理器查看进程,如果未占用cpu时间且有多个线程,则形成了死锁
#3
when you create a thread, output its threadid, function of the thread
at runtime,枚举进程中所有线程,看他们的cpu时间
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
*/
HANDLE hthread=OpenThread(THREAD_QUERY_INFORMATION,FALSE, tie.te32.th32ThreadID);
if(hthread)
{
ReportThreadTime(hthread,tie.te32.th32ThreadID,false,"");
CloseHandle(hthread);
}
else
{
}
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
// Do not forget to clean up the snapshot object.
CloseHandle (hThreadSnap);
at runtime,枚举进程中所有线程,看他们的cpu时间
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
*/
HANDLE hthread=OpenThread(THREAD_QUERY_INFORMATION,FALSE, tie.te32.th32ThreadID);
if(hthread)
{
ReportThreadTime(hthread,tie.te32.th32ThreadID,false,"");
CloseHandle(hthread);
}
else
{
}
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
// Do not forget to clean up the snapshot object.
CloseHandle (hThreadSnap);
#4
void ThreadClass::ReportThreadTime(HANDLE hthread,DWORD threadid, bool log, LPCTSTR threadname)
{
FILETIME createtime;
FILETIME exittime;
FILETIME kernaltime;
FILETIME usertime;
BOOL ret=GetThreadTimes(hthread,&createtime,&exittime,&kernaltime,&usertime);
if(ret==0)
{
//error
LPVOID lpMsgBuf;
FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
GetLastError(),
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
(LPTSTR) &lpMsgBuf,
0,
NULL
);
// Process any inserts in lpMsgBuf.
// ...
// Display the string.
//MessageBox( NULL, (LPCTSTR)lpMsgBuf, "Error", MB_OK | MB_ICONINFORMATION );
g_Log.Debug("%s:%d GetThreadTimes error:%s",__FILE__,__LINE__,(char*)lpMsgBuf);
// Free the buffer.
LocalFree( lpMsgBuf );
return;
}
SYSTEMTIME stkernal;
SYSTEMTIME stuser;
FileTimeToSystemTime(&kernaltime,&stkernal);
FileTimeToSystemTime(&usertime,&stuser);
std::ostringstream oss;
oss<<"ThreadClass("<<threadid<<","<<threadname<<") profile(d:h:m:s:ms), user time "<<stuser.wDay<<":"
<<stuser.wHour<<":"<<stuser.wMinute<<":"<<stuser.wSecond<<":"<<stuser.wMilliseconds;
oss<<"; kernal time "<<stkernal.wDay<<":"<<stkernal.wHour<<":"<<stkernal.wMinute<<":"
<<stkernal.wSecond<<":"<<stkernal.wMilliseconds;
}
{
FILETIME createtime;
FILETIME exittime;
FILETIME kernaltime;
FILETIME usertime;
BOOL ret=GetThreadTimes(hthread,&createtime,&exittime,&kernaltime,&usertime);
if(ret==0)
{
//error
LPVOID lpMsgBuf;
FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
GetLastError(),
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
(LPTSTR) &lpMsgBuf,
0,
NULL
);
// Process any inserts in lpMsgBuf.
// ...
// Display the string.
//MessageBox( NULL, (LPCTSTR)lpMsgBuf, "Error", MB_OK | MB_ICONINFORMATION );
g_Log.Debug("%s:%d GetThreadTimes error:%s",__FILE__,__LINE__,(char*)lpMsgBuf);
// Free the buffer.
LocalFree( lpMsgBuf );
return;
}
SYSTEMTIME stkernal;
SYSTEMTIME stuser;
FileTimeToSystemTime(&kernaltime,&stkernal);
FileTimeToSystemTime(&usertime,&stuser);
std::ostringstream oss;
oss<<"ThreadClass("<<threadid<<","<<threadname<<") profile(d:h:m:s:ms), user time "<<stuser.wDay<<":"
<<stuser.wHour<<":"<<stuser.wMinute<<":"<<stuser.wSecond<<":"<<stuser.wMilliseconds;
oss<<"; kernal time "<<stkernal.wDay<<":"<<stkernal.wHour<<":"<<stkernal.wMinute<<":"
<<stkernal.wSecond<<":"<<stkernal.wMilliseconds;
}
#5
还有就是提供接口能够随时察看程序中的资源情况,队列大小
#1
用CEvent或是CCriticalSection类来加个临界区
#2
在程序运行当中,用windows的任务管理器查看进程,如果未占用cpu时间且有多个线程,则形成了死锁
#3
when you create a thread, output its threadid, function of the thread
at runtime,枚举进程中所有线程,看他们的cpu时间
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
*/
HANDLE hthread=OpenThread(THREAD_QUERY_INFORMATION,FALSE, tie.te32.th32ThreadID);
if(hthread)
{
ReportThreadTime(hthread,tie.te32.th32ThreadID,false,"");
CloseHandle(hthread);
}
else
{
}
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
// Do not forget to clean up the snapshot object.
CloseHandle (hThreadSnap);
at runtime,枚举进程中所有线程,看他们的cpu时间
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
*/
HANDLE hthread=OpenThread(THREAD_QUERY_INFORMATION,FALSE, tie.te32.th32ThreadID);
if(hthread)
{
ReportThreadTime(hthread,tie.te32.th32ThreadID,false,"");
CloseHandle(hthread);
}
else
{
}
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
// Do not forget to clean up the snapshot object.
CloseHandle (hThreadSnap);
#4
void ThreadClass::ReportThreadTime(HANDLE hthread,DWORD threadid, bool log, LPCTSTR threadname)
{
FILETIME createtime;
FILETIME exittime;
FILETIME kernaltime;
FILETIME usertime;
BOOL ret=GetThreadTimes(hthread,&createtime,&exittime,&kernaltime,&usertime);
if(ret==0)
{
//error
LPVOID lpMsgBuf;
FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
GetLastError(),
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
(LPTSTR) &lpMsgBuf,
0,
NULL
);
// Process any inserts in lpMsgBuf.
// ...
// Display the string.
//MessageBox( NULL, (LPCTSTR)lpMsgBuf, "Error", MB_OK | MB_ICONINFORMATION );
g_Log.Debug("%s:%d GetThreadTimes error:%s",__FILE__,__LINE__,(char*)lpMsgBuf);
// Free the buffer.
LocalFree( lpMsgBuf );
return;
}
SYSTEMTIME stkernal;
SYSTEMTIME stuser;
FileTimeToSystemTime(&kernaltime,&stkernal);
FileTimeToSystemTime(&usertime,&stuser);
std::ostringstream oss;
oss<<"ThreadClass("<<threadid<<","<<threadname<<") profile(d:h:m:s:ms), user time "<<stuser.wDay<<":"
<<stuser.wHour<<":"<<stuser.wMinute<<":"<<stuser.wSecond<<":"<<stuser.wMilliseconds;
oss<<"; kernal time "<<stkernal.wDay<<":"<<stkernal.wHour<<":"<<stkernal.wMinute<<":"
<<stkernal.wSecond<<":"<<stkernal.wMilliseconds;
}
{
FILETIME createtime;
FILETIME exittime;
FILETIME kernaltime;
FILETIME usertime;
BOOL ret=GetThreadTimes(hthread,&createtime,&exittime,&kernaltime,&usertime);
if(ret==0)
{
//error
LPVOID lpMsgBuf;
FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
GetLastError(),
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
(LPTSTR) &lpMsgBuf,
0,
NULL
);
// Process any inserts in lpMsgBuf.
// ...
// Display the string.
//MessageBox( NULL, (LPCTSTR)lpMsgBuf, "Error", MB_OK | MB_ICONINFORMATION );
g_Log.Debug("%s:%d GetThreadTimes error:%s",__FILE__,__LINE__,(char*)lpMsgBuf);
// Free the buffer.
LocalFree( lpMsgBuf );
return;
}
SYSTEMTIME stkernal;
SYSTEMTIME stuser;
FileTimeToSystemTime(&kernaltime,&stkernal);
FileTimeToSystemTime(&usertime,&stuser);
std::ostringstream oss;
oss<<"ThreadClass("<<threadid<<","<<threadname<<") profile(d:h:m:s:ms), user time "<<stuser.wDay<<":"
<<stuser.wHour<<":"<<stuser.wMinute<<":"<<stuser.wSecond<<":"<<stuser.wMilliseconds;
oss<<"; kernal time "<<stkernal.wDay<<":"<<stkernal.wHour<<":"<<stkernal.wMinute<<":"
<<stkernal.wSecond<<":"<<stkernal.wMilliseconds;
}
#5
还有就是提供接口能够随时察看程序中的资源情况,队列大小