主要代码如下:
DWORD dwTotal = m_arrFileInfo.GetSize();
for ( int i = 0 ; i < m_arrFileInfo.GetSize() ; i++ )
{
pDownloadFileInfo = NULL;
pDownloadFileInfo = new DOWNLOAD_FILE_INFO;
memcpy(pDownloadFileInfo , &(m_arrFileInfo[i]),sizeof(DOWNLOAD_FILE_INFO));
DWORD dwThreadId; if(i < MAX_EXECUTE_THREAD)
{
hThread[i] = CreateThread(
NULL, // default security attributes
0, // use default stack size
ThreadFunc, // thread function
pDownloadFileInfo, // argument to thread function
0, // use default creation flags
&dwThreadId);
hExecuteThread[i] = hThread[i];
}
else
{
//超过MAX_EXECUTE_THREAD的线程暂时挂起
hThread[i] = CreateThread(
NULL, // default security attributes
0, // use default stack size
ThreadFunc, // thread function
pDownloadFileInfo, // argument to thread function
CREATE_SUSPENDED, // use default creation flags
&dwThreadId);
SetThreadPriority(hThread[i],THREAD_PRIORITY_IDLE);
}
} dwCount = MAX_EXECUTE_THREAD; iWant = MAX_EXECUTE_THREAD;//resume的线程的索引值是从MAX_EXECUTE_THREAD开始 BOOL bQuit = FALSE;
int iCurDown = 0;
while (!bQuit)
{
MSG msg;
int rc=0;
if(dwCount == MAX_EXECUTE_THREAD)
SetDlgItemText(IDC_STATIC_CUR_DOWN,m_arrFileInfo[0].tcFileName); rc = MsgWaitForMultipleObjects(dwCount,hExecuteThread,FALSE,INFINITE,QS_ALLEVENTS); if (rc >= WAIT_OBJECT_0 && rc < WAIT_OBJECT_0 + dwCount)
{
//得到当前通知要结束的线程
int index = rc - WAIT_OBJECT_0;
//所有的线程都已经运行了,此时只需要控制执行中的线程了
if(iWant == dwTotal)
{
hExecuteThread[index] = hExecuteThread[dwCount-1];
hExecuteThread[dwCount-1] = 0;
dwCount--;
}
else
{
iWant++;
hExecuteThread[index] = hThread[iWant];
::SendMessage(m_hWnd,WM_RESUME_THREAD,NULL,(LPARAM)hThread[iWant]);
} if(dwCount == 0)
{
m_prsTotalFile.SetPos(100);
bQuit = TRUE;
}
}
else if(rc == WAIT_OBJECT_0 + dwCount)
{
//窗口继续消息处理
while (PeekMessage(&msg,NULL,0,0,PM_REMOVE))
{
if(msg.message == WM_QUIT)
{
bQuit = TRUE;
break;
}
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
有时创建工作线程时,会出现,有时候创建挂起线程时,也会出现!不知道问题在哪里,我已经设置了/stack的值。
DWORD dwTotal = m_arrFileInfo.GetSize();
for ( int i = 0 ; i < m_arrFileInfo.GetSize() ; i++ )
{
pDownloadFileInfo = NULL;
pDownloadFileInfo = new DOWNLOAD_FILE_INFO;
memcpy(pDownloadFileInfo , &(m_arrFileInfo[i]),sizeof(DOWNLOAD_FILE_INFO));
DWORD dwThreadId; if(i < MAX_EXECUTE_THREAD)
{
hThread[i] = CreateThread(
NULL, // default security attributes
0, // use default stack size
ThreadFunc, // thread function
pDownloadFileInfo, // argument to thread function
0, // use default creation flags
&dwThreadId);
hExecuteThread[i] = hThread[i];
}
else
{
//超过MAX_EXECUTE_THREAD的线程暂时挂起
hThread[i] = CreateThread(
NULL, // default security attributes
0, // use default stack size
ThreadFunc, // thread function
pDownloadFileInfo, // argument to thread function
CREATE_SUSPENDED, // use default creation flags
&dwThreadId);
SetThreadPriority(hThread[i],THREAD_PRIORITY_IDLE);
}
} dwCount = MAX_EXECUTE_THREAD; iWant = MAX_EXECUTE_THREAD;//resume的线程的索引值是从MAX_EXECUTE_THREAD开始 BOOL bQuit = FALSE;
int iCurDown = 0;
while (!bQuit)
{
MSG msg;
int rc=0;
if(dwCount == MAX_EXECUTE_THREAD)
SetDlgItemText(IDC_STATIC_CUR_DOWN,m_arrFileInfo[0].tcFileName); rc = MsgWaitForMultipleObjects(dwCount,hExecuteThread,FALSE,INFINITE,QS_ALLEVENTS); if (rc >= WAIT_OBJECT_0 && rc < WAIT_OBJECT_0 + dwCount)
{
//得到当前通知要结束的线程
int index = rc - WAIT_OBJECT_0;
//所有的线程都已经运行了,此时只需要控制执行中的线程了
if(iWant == dwTotal)
{
hExecuteThread[index] = hExecuteThread[dwCount-1];
hExecuteThread[dwCount-1] = 0;
dwCount--;
}
else
{
iWant++;
hExecuteThread[index] = hThread[iWant];
::SendMessage(m_hWnd,WM_RESUME_THREAD,NULL,(LPARAM)hThread[iWant]);
} if(dwCount == 0)
{
m_prsTotalFile.SetPos(100);
bQuit = TRUE;
}
}
else if(rc == WAIT_OBJECT_0 + dwCount)
{
//窗口继续消息处理
while (PeekMessage(&msg,NULL,0,0,PM_REMOVE))
{
if(msg.message == WM_QUIT)
{
bQuit = TRUE;
break;
}
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
有时创建工作线程时,会出现,有时候创建挂起线程时,也会出现!不知道问题在哪里,我已经设置了/stack的值。
把ThreadFunc 的代码贴来
注意线程安全
1.创建一个事件:CreateEvent() 来监控每个线程;
2.把原来判断线程创建的最大数改成WaitForMultipleObjects();里面监控的参数设置为最大的线程数,在此,如有线程执行完毕,则采取相应的措施
DWORD WINAPI ThreadFunc( LPVOID lpParam )
{
DOWNLOAD_FILE_INFO* threadparam=(DOWNLOAD_FILE_INFO*)lpParam;
char httpbuff[HTTPBUFLEN];
TCHAR szCause[255];
CString strBuffer; EnterCriticalSection(&criticalSection); if(lstrlen(threadparam->tcFileName)<=0) return 1; TRY
{
CInternetSession mysession;
CStdioFile *remotefile = mysession.OpenURL(threadparam->tcDownloadUrl,1,INTERNET_FLAG_TRANSFER_BINARY|INTERNET_FLAG_RELOAD);
CFile myfile(threadparam->tcFileName, CFile::modeCreate|CFile::modeWrite|CFile::typeBinary);
int numbytes;
CString strName;/* CFileStatus fileStatus;
CFile::GetStatus(threadparam->tcFileName, fileStatus);*/ while (numbytes = remotefile->Read(httpbuff, HTTPBUFLEN))
myfile.Write(httpbuff, numbytes);
myfile.Close();
//下载成功的通知
::SendMessage(m_hThisWnd,WM_DOWNLOAD_STEP,NULL,(LPARAM)threadparam);
if(threadparam)
{
delete threadparam;
threadparam = NULL;
OutputDebugString(_T("Delete successful!"));
}
}
CATCH_ALL(error)
{
LeaveCriticalSection(&criticalSection);
error->GetErrorMessage(szCause,254,NULL);
}
END_CATCH_ALL;
LeaveCriticalSection(&criticalSection);
return 0;
}const int BASE_LEN = 128;
const int MAX_EXECUTE_THREAD = 10;
const int K_SIZE = 1024;
const int HTTPBUFLEN = BASE_LEN*K_SIZE*10;typedef struct {
TCHAR tcFileName[2*BASE_LEN];
TCHAR tcDownloadUrl[2*BASE_LEN];
}DOWNLOAD_FILE_INFO;
wzbhbb() MsgWaitForMultipleObjects 比WaitForMultipleObjects()更合理!
倒是可以试试监视每个线程!
谢谢!
GetExceptionCode
hThread[i] = CreateThread(
NULL, // default security attributes
4096, //《-------用这个试试看?要比httpbuff和szCause加起来都要大
ThreadFunc, // thread function
pDownloadFileInfo, // argument to thread function
0, // use default creation flags
&dwThreadId);
hExecuteThread[i] = hThread[i];
}
是在linker中设置的/STACK设置错了,改为CreateThread中设置就对了!