我想写一个多线程的 下载程序
1。一个全局的函数 UINT DownLoadFunction(LPVOID lParam)
2。一个下载线程类 DownloadThead
AfxBeginThread(::DownLoadFunction, this);
while (thread_finished_flag == FALSE){ }
在构造函数中就启动 线程
3。在主程序中 生成多个 DownloadThead 类。可程序 好象 就只有一个 线程在运行, 在运行时, 我不能关闭程序,连拖动都不行,只有强行关闭(任务管理器),如果是多线程,我完全可以终止程序。
请高手指点!!!
1。一个全局的函数 UINT DownLoadFunction(LPVOID lParam)
2。一个下载线程类 DownloadThead
AfxBeginThread(::DownLoadFunction, this);
while (thread_finished_flag == FALSE){ }
在构造函数中就启动 线程
3。在主程序中 生成多个 DownloadThead 类。可程序 好象 就只有一个 线程在运行, 在运行时, 我不能关闭程序,连拖动都不行,只有强行关闭(任务管理器),如果是多线程,我完全可以终止程序。
请高手指点!!!
for(int i=0; i<stringArray.GetSize(); i++ ){
fileInfo = (CStringArray *)stringArray.GetAt(i);
DownloadThead dThead(down,fileInfo->GetAt(0),path+fileInfo->GetAt(1));
}其中 down 是一个专门负责下载的类,
fileInfo->GetAt(0) ,path+fileInfo->GetAt(1)
是一些参数(现在的URL,本地路径)可以直接 用down(fileInfo->GetAt(0) ,path+fileInfo->GetAt(1));
来完成下载,但这只是但线程的。请指教!!!
for(int i=0; i<stringArray.GetSize(); i++ ){
fileInfo = (CStringArray *)stringArray.GetAt(i);
DownloadThead dThead(down,fileInfo->GetAt(0),path+fileInfo->GetAt(1));
}其中 down 是一个专门负责下载的类,
fileInfo->GetAt(0) ,path+fileInfo->GetAt(1)
是一些参数(现在的URL,本地路径)可以直接 用down(fileInfo->GetAt(0) ,path+fileInfo->GetAt(1));
来完成下载,但这只是但线程的。请指教!!!
DownloadThead::DownloadThead(CHttpDownload down, CString downloadUrl,CString savePath)
{
thread_finished_flag = FALSE;
this->downloadUrl = downloadUrl;
this->savePath = savePath;
this->down = down; CWinThread *ct = AfxBeginThread(::DownLoadFunction, this); while (thread_finished_flag == FALSE){
}
}
pDownI->thread_finished_flag = TRUE;
return -1;
}
pDownI->down.Download( pDownI->downloadUrl , pDownI->savePath);
pDownI->thread_finished_flag = TRUE;
return 0;
UINT DownLoadFunction(LPVOID lParam)
{
DownloadThead * pDownI = (DownloadThead *)lParam; if (pDownI == NULL){
pDownI->thread_finished_flag = TRUE;
return -1;
}
pDownI->down.Download( pDownI->downloadUrl , pDownI->savePath);
pDownI->thread_finished_flag = TRUE;
return 0;}
}到了这一句,主线程就进无限循环了,怎么创建下一个线程?
如果不是必须的话,你可以去掉
while (thread_finished_flag == FALSE){
}
这一句.
PostMessage
到主threadBOOL PostMessage(
HWND hWnd, // handle of destination window
UINT Msg, // message to post
WPARAM wParam, // first message parameter
LPARAM lParam // second message parameter
);
fileInfo = (CStringArray *)stringArray.GetAt(i);
new DownloadThead(down,fileInfo->GetAt(0),path+fileInfo->GetAt(1));
}
1。线程退出时提示(没有运行完): Detected memory leaks!
2。仍然不能拖动!:(
请在指教
你删去了死循环后,主线程线先结束了而导致子线程被终止。
具体点好吗?:(((((
>PostMessage
>到主thread
DWORD idThread, // thread identifier
UINT Msg, // message to post
WPARAM wParam, // first message parameter
LPARAM lParam // second message parameter
);那 idThread 是什么?
Msg 是什么?
由于对vc 是菜鸟
多指点
UINT Msg: 你想要Post的消息,呵呵...UINT DownLoadFunction(LPVOID lParam)
{
DownloadThead * pDownI = (DownloadThead *)lParam; if (pDownI == NULL){
pDownI->thread_finished_flag = TRUE;
return -1;
}
pDownI->down.Download( pDownI->downloadUrl , pDownI->savePath);
//pDownI->thread_finished_flag = TRUE;
PostThreadMessage (theApp.m_nThreadID, 线程结束消息, 0, GetCurrentThreadId()); //呵呵
return 0;}
LoveTide(一个月挣多少钱知足?)
"线程结束消息"是不是我定义一个 常量(还是已经有的)
那在主线程中要做相应的处理代码吗?(还是系统自己处理)
E:\project\Éý¼¶Èí¼þ\¸´¼þ Éý¼¶Ä£¿é\DownloadThead.cpp(63) : error C2228: left of '.m_nThreadID' must have class/struct/union type
UINT DownLoadFunction(LPVOID lParam) 是全局函数 出现错误
PostThreadMessage (theApp.m_nThreadID, WM_QUIT
, 0, GetCurrentThreadId()); //呵呵一运行 就退出
DownloadThead::DownloadThead(CHttpDownload down, CString downloadUrl,CString savePath)
{
thread_finished_flag = FALSE;
this->downloadUrl = downloadUrl;
this->savePath = savePath;
this->down = down; CWinThread *ct = AfxBeginThread(::DownLoadFunction, this); //while (thread_finished_flag == FALSE){}
// ????????
}
该怎么处理呢???
MSG msg;
while( ::GetMessage( &msg, NULL, 0, 0 ) )
{
if( msg.message == WM_THERD_END )
break;
else
::DispatchMessage( &msg );
}
还是不行,请大虾在指点!!!!
推荐一本好书,好象叫《win32多线程....》
{
thread_finished_flag = FALSE;
this->downloadUrl = downloadUrl;
this->savePath = savePath;
this->down = down; CWinThread *ct = AfxBeginThread(::DownLoadFunction, this);
//////////////////////
static i=0; //你的线程数
// HANDLE thread[4];
thread[i++]=ct->m_hThread
//while (thread_finished_flag == FALSE){}
// ????????
}主线程中
HANDLE thread[stringArray.GetSize()]; //你的线程数
...
WaitForMultipObjects(stringArray.GetSize(),thread,TRUE,INFINITE);
//while (thread_finished_flag == FALSE){
//}
Kill Dead Another,在构造中CreateEvent Kill与Dead,
在InitInstance中:
while (WaitForSingleObject(m_hEventKill, 0) == WAIT_TIMEOUT)
{
进入临界区进行资源访问,也就是可以DownloadFunction();
}
在析构中CloseHandle Kill与Dead,在Delete中SetEvent Dead Another.
1。线程退出时提示(没有运行完): Detected memory leaks!
_______
上面已经有人解释,如果要求不高,完全可以忽略。
2。仍然不能拖动!
——————————————————
while (thread_finished_flag == FALSE){
}
去掉了么?不然就是你在别的地方,还有死循环。——————————————
如果你只是要程序能运行,这样就可以了。如果要它好好运行,就要照楼上的
话改。
我按照 大虾 说的方法 遇到 2 个问题:1。
static i=0; //你的线程数
// HANDLE thread[4]; 我该在什么地方定义?其中的4是不是最大线程数?还是具有其他含义?
thread[i++]=ct->m_hThread 2。主线程中
HANDLE thread[stringArray.GetSize()]; //你的线程数
stringArray.GetSize() 是变量,不可能定义HANDLE thread[变量]
我可以直接定义一个较大的数,有影响吗?
wacky(笨笨狗) 能够将你讲的方法详细点吗?
先谢了!
定义成全局变量吧。
我不知你有多少线程,4是随意写的,可以直接定义一个较大的数(我在书上看到的,说一个进程拥有的资源数,包括各种内核,图标等,最大可到1万个)。 我建议你看看侯捷译的《Win32多线程编程〉,或,《Windows 核心编程>
一句话也说不清的,建议先看看多线程编程的书,我有一本电子的,若要,请来信索取:[email protected]
caitou123(自向红尘取烦恼)
我按照 大虾的方法做了,但感觉还是没对我把线程的代码改成
for(int i=0; i<1000; i++){
TRACE("%d ",i);
}但输出的结果是:
0,1,2,3,4,..658
0,1,2,3,4,..194
0,1,2,3,4,..194没有什么其他异常的输出
如果是在线程里加的,for(int i=0; i<1000; i++){
TRACE("%d ",i);
}
也是对的,因为线程创建后,就由cpu来调度了。
我说的方法,就是保证在子线程未结束时,禁止主线程的终止。
fileInfo = (CStringArray *)stringArray.GetAt(i);
new DownloadThead(down,fileInfo->GetAt(0),path+fileInfo->GetAt(1));
}这里就是 创建线程啊!
3236(Arcol) 可以具体点好吗?
for(int i=0; i<stringArray.GetSize(); i++ ){
fileInfo = (CStringArray *)stringArray.GetAt(i);
new DownloadThead(down,fileInfo->GetAt(0),path+fileInfo->GetAt(1));
}
当中,DownloadThead构造时,你在最后用了一句
while (thread_finished_flag == FALSE){}的无限循环,到底为什么?要是这样的话,for循环只跑了一次,就被阻塞了,你不是说了要建立好几个线程吗?但现在这样只能等到第2个线程跑完才能建立第3个线程,第3个线程跑完才能建立第4个线程,...,这样子你就永远都不能同时建立好几个线程。再说,阻塞是占用CPU资源的,所以你的程序就象死掉的样子。
还有你的程序是基于SDK还是MFC的?最好也说清楚至于各位所回答的都是关于线程同步的问题,主要用的是event(使用CreateEvent和WaitForSingleObject等方法辅助)、msg(使用PostThreadMessage 和GetMessage等方法辅助),当然除了这两种方法以外还有mutex、Semaphore,dde、共享内存、系统环境量、本地tcp通讯,管道、邮槽、甚至文件、数据库等都可以进行线程或进程同步、通信。你所用的while (thread_finished_flag == FALSE){}其实也是一种方法,只是用得不对而儿我看你对线程的概念是有一定的误会,先看看书(按我所说的方法查一下msdn),然后把你的问题和程序整理一下,再开一帖吧
现在我只讨论第2点,也就是说你的DownLoadFunction中遇到return指令。
理论上DownLoadFunction这个线程过程应是一个死循环,就象阻塞了一样,直到你需要它退出时才发一个exit message(由主线程发出)。
例如:while(1){...};//但如果只是这样就会占用100%的CPU资源,因为程序一直在跑,没机会交回操作系统,这个死循环也太死了。
因此就有了一个while(::GetMessage(&msg,NULL,0,0)){...};
当中GetMessage就是交回操作系统处理,如果没有message,线程就被挂起,GetMessage不返回值给你,就象是你在等待操作系统回答,但操作系统死活都不理你,它干别的事去了。
同样用WaitForSingleObjectcs或WaitForMultipObjectcs也能达到同样的效果。
如果你的程序是基于MFC写的,哪就不用担心,MFC已经帮你做了,其实如果把MFC框架展开,也会找到类似while(::GetMessage(&msg,NULL,0,0)){...}的语句。以上我所提到的"程序"只是指一般的程序,不包括组件,dll等特殊的程式
UINT DownLoadFunction(LPVOID lParam)
{
DownloadThead * pDownI = (DownloadThead *)lParam; if (pDownI == NULL){
pDownI->thread_finished_flag = TRUE;
return -1;
}
pDownI->down.Download( pDownI->downloadUrl , pDownI->savePath); pDownI->thread_finished_flag = TRUE;
return 0;
}
最开始代码是这样的,程序可以执行,唯一 一个缺点是,主线程好象阻塞了,对话筐不能拖动。(我的本意是,让子线程执行下载,主线程控制下载线程的开始,暂停,停止),现在连主线程的对话筐都锁死了。
while (thread_finished_flag == FALSE){};吗?
这和我所说的while(1){...};有什么区别?
都是死循环,虽然有逃生机会,但也太死了吧。
要注意,操作系统根本就没机会处理其它东西,你的对话框就别想动了。我看,你的思想是对的,但做法却错了,要记住,windows程序不再是过程程序,它是由事件驱动的。就说你的程序,线程控制下载线程的开始,暂停,停止是对的,但在同一个过程(函数)里面不应该同时处理子线程的“开始,暂停,停止”三个问题。你试着往对话框放3个按扭,分别表示“开始,暂停,停止”三个问题,然后在3个OnClick事件里分别处理这3个问题,你就会更清楚什么叫事件驱动了。在主线程中,一个事件(例如OnClick)响应后,应立即或尽快返回给系统(就是退出那个响应函数),而你呢?却一直在while()里头转!哪不是你在等操作系统,而是系统在等你啊!系统还有机会处理其它事件吗?另外,关于线程问题中,还有一个优先级问题,一般来说主线程要高于分线程,但所有线程都不应高于标准级,如非工程或驱动核心代码不能使用高优先级,默认就如此(莫非你改过?)。你可以烟酒烟酒。
请各位大侠指点
http://expert.csdn.net/Expert/topic/1106/1106349.xml?temp=3.846377E-02
pDownI->down.Download里头究竟在干嘛?
是不是很复杂的?如果太复杂,这里会占用很多CPU资源的,尤其是在网络访问要等待时,而在等待时又不让系统干别的事,结果会导致子线程占用CPU过多,而令主线程没时间处理。所以有2点可以改进改进1.子线程也完全使用事件驱动的方式,就是借助WaitForMultipObjectcs等方法。
2.适当降底子线程优先级。