我想写一个多线程的 下载程序
1。一个全局的函数 UINT DownLoadFunction(LPVOID lParam)
2。一个下载线程类 DownloadThead 
   AfxBeginThread(::DownLoadFunction, this);
    while (thread_finished_flag == FALSE){ }
   在构造函数中就启动 线程
3。在主程序中 生成多个 DownloadThead 类。可程序 好象 就只有一个 线程在运行, 在运行时, 我不能关闭程序,连拖动都不行,只有强行关闭(任务管理器),如果是多线程,我完全可以终止程序。
 
请高手指点!!!

解决方案 »

  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));
    来完成下载,但这只是但线程的。请指教!!!
      

  2.   

    主线程中 
    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));
    来完成下载,但这只是但线程的。请指教!!!
      

  3.   

    DownloadThead(down,fileInfo->GetAt(0),path+fileInfo->GetAt(1));这个函数是启动子线程的?
      

  4.   

    对, 
    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){

    }
    }
      

  5.   

    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;
      

  6.   

    以上是 
    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;}
      

  7.   

    while (thread_finished_flag == FALSE){

    }到了这一句,主线程就进无限循环了,怎么创建下一个线程?
      

  8.   

    你主线程为什么要 thread_finished_flag == FALSE 等待这个子线程完成?
    如果不是必须的话,你可以去掉
    while (thread_finished_flag == FALSE){

    }
    这一句.
      

  9.   

    thread结束后 post 给主thread一个TheadTerminated 的消息都好过 你在这里while循环...
      

  10.   

    DownloadThead    dThead(down,fileInfo->GetAt(0),path+fileInfo->GetAt(1));大约是局部变量 DTHREAD 被销毁了. 你用NEW创建DTHREAD试试
      

  11.   

    我该怎么
    PostMessage
    到主threadBOOL PostMessage(
      HWND hWnd,      // handle of destination window
      UINT Msg,       // message to post
      WPARAM wParam,  // first message parameter
      LPARAM lParam   // second message parameter
    );
      

  12.   

    for(int i=0; i<stringArray.GetSize(); i++ ){
       fileInfo = (CStringArray *)stringArray.GetAt(i);
       new DownloadThead(down,fileInfo->GetAt(0),path+fileInfo->GetAt(1));
    }
      

  13.   

    有2个问题:
    1。线程退出时提示(没有运行完): Detected memory leaks!
    2。仍然不能拖动!:(
    请在指教
      

  14.   

    为什么不用CreatEvent生成i个事件变量,在子线程设置事件变量,在主线程中用WaitForMultipObjectcs来等待子线程完成。
      你删去了死循环后,主线程线先结束了而导致子线程被终止。
      

  15.   

    TO:caitou123(自向红尘取烦恼) 
    具体点好吗?:(((((
      

  16.   

    PostThreadMessage...>我该怎么
    >PostMessage
    >到主thread
      

  17.   

    BOOL PostThreadMessage(
      DWORD idThread, // thread identifier
      UINT Msg,       // message to post
      WPARAM wParam,  // first message parameter
      LPARAM lParam   // second message parameter
    );那 idThread 是什么?
    Msg 是什么?
    由于对vc 是菜鸟
    多指点
      

  18.   

    DWORD idThread: 每一个CWinThread都有一个ID,呵呵...
    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;}
      

  19.   

    TO:
      LoveTide(一个月挣多少钱知足?)  
    "线程结束消息"是不是我定义一个 常量(还是已经有的)
    那在主线程中要做相应的处理代码吗?(还是系统自己处理)
      

  20.   

    E:\project\&Eacute;&yacute;&frac14;&para;&Egrave;í&frac14;&thorn;\&cedil;&acute;&frac14;&thorn; &Eacute;&yacute;&frac14;&para;&Auml;&pound;&iquest;é\DownloadThead.cpp(63) : error C2065: 'theApp' : undeclared identifier
    E:\project\&Eacute;&yacute;&frac14;&para;&Egrave;í&frac14;&thorn;\&cedil;&acute;&frac14;&thorn; &Eacute;&yacute;&frac14;&para;&Auml;&pound;&iquest;é\DownloadThead.cpp(63) : error C2228: left of '.m_nThreadID' must have class/struct/union type
    UINT DownLoadFunction(LPVOID lParam) 是全局函数 出现错误
      

  21.   


    PostThreadMessage (theApp.m_nThreadID, WM_QUIT
    , 0, GetCurrentThreadId());  //呵呵一运行 就退出
      

  22.   

    我定义了一个常量但我在 
    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){}
               // ???????? 
    }
    该怎么处理呢???
      

  23.   

    我在 DownloadThead::DownloadThead(CHttpDownload down, CString  downloadUrl,CString savePath) 加入
    MSG msg;
    while( ::GetMessage( &msg, NULL, 0, 0 ) )
    {
    if( msg.message ==  WM_THERD_END )
    break;
    else
                         ::DispatchMessage( &msg );
              }
    还是不行,请大虾在指点!!!!
      

  24.   

    建议使用WaitForSingleObject等待信号量,而不是while
    推荐一本好书,好象叫《win32多线程....》
      

  25.   

    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);
    //////////////////////
       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){
    //}   
      

  26.   

    在你的子线程中定义三个HANDLE信号变量与临界区锁变量,
    Kill Dead Another,在构造中CreateEvent Kill与Dead,
    在InitInstance中:
    while (WaitForSingleObject(m_hEventKill, 0) == WAIT_TIMEOUT)
    {
       进入临界区进行资源访问,也就是可以DownloadFunction();
    }
    在析构中CloseHandle Kill与Dead,在Delete中SetEvent Dead Another.
      

  27.   

    有2个问题:
    1。线程退出时提示(没有运行完): Detected memory leaks!
    _______
    上面已经有人解释,如果要求不高,完全可以忽略。
    2。仍然不能拖动!
    ——————————————————
    while (thread_finished_flag == FALSE){

    }
    去掉了么?不然就是你在别的地方,还有死循环。——————————————
    如果你只是要程序能运行,这样就可以了。如果要它好好运行,就要照楼上的
    话改。
      

  28.   

    TO:  caitou123(自向红尘取烦恼) 
    我按照 大虾 说的方法 遇到 2 个问题:1。
         static  i=0;      //你的线程数
    // HANDLE  thread[4]; 我该在什么地方定义?其中的4是不是最大线程数?还是具有其他含义?
         thread[i++]=ct->m_hThread 2。主线程中 
      HANDLE  thread[stringArray.GetSize()];   //你的线程数
      stringArray.GetSize() 是变量,不可能定义HANDLE  thread[变量]
      我可以直接定义一个较大的数,有影响吗? 
      

  29.   

    TO:
      wacky(笨笨狗) 能够将你讲的方法详细点吗?
    先谢了!
      

  30.   

    HANDLE  thread[4] 就是主线程中的 HANDLE  thread[stringArray.GetSize()];    
     定义成全局变量吧。
       我不知你有多少线程,4是随意写的,可以直接定义一个较大的数(我在书上看到的,说一个进程拥有的资源数,包括各种内核,图标等,最大可到1万个)。  我建议你看看侯捷译的《Win32多线程编程〉,或,《Windows 核心编程>
      

  31.   

    因为你定义的是多线程是基于WinThread的,所以定义信号变量HANDLE是为了使线程同步,并且不出现资源强占与死锁。
    一句话也说不清的,建议先看看多线程编程的书,我有一本电子的,若要,请来信索取:[email protected]
      

  32.   

    TO:
     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没有什么其他异常的输出
       
      

  33.   

    DownLoadFunction应该为DownloadThead类的成员函数
      

  34.   

    "没有什么其他异常的输出"  是什么意思?
    如果是在线程里加的,for(int i=0; i<1000; i++){
    TRACE("%d ",i);
    }
    也是对的,因为线程创建后,就由cpu来调度了。
    我说的方法,就是保证在子线程未结束时,禁止主线程的终止。
       
      

  35.   

    當你創建sub thread的時候,將ThreadID保存入一個數組,然後在主纖程末,用WaitForMultipleObjects()函數,具體可以參攷<Windows核心編程>,樓上几位說得很清楚了啊,順便參攷MSDN就行了。
      

  36.   

    问题出在while (thread_finished_flag == FALSE){ }中把它去掉,或插入sleep代替线程之间同步不应用thread_finished_flag,这样会阻塞的,你可以试用event或msg代替老兄,你哪儿建了第二个线程了?
      

  37.   

    for(int i=0; i<stringArray.GetSize(); i++ ){
       fileInfo = (CStringArray *)stringArray.GetAt(i);
       new DownloadThead(down,fileInfo->GetAt(0),path+fileInfo->GetAt(1));
    }这里就是 创建线程啊!
      

  38.   

    TO:
        3236(Arcol) 可以具体点好吗?
      

  39.   

    对不起,明天要考试,过两天我会回来的你还是开个新帖吧,把你的问题说清楚,说详细一点到现在我还不是很清楚,你需要的是什么象下面你写的程序
    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),然后把你的问题和程序整理一下,再开一帖吧
      

  40.   

    看候捷的《win32多线程》。那里有一些例子。
      

  41.   

    线程结束有3个条件1.你使用代码强制令它终止。2.线程函数运行结束(不论是否正常结束)。3.主线程(进程)结束。(可以说成是创建线程的父线程)我估计你的问题是第2或第3点。
    现在我只讨论第2点,也就是说你的DownLoadFunction中遇到return指令。
    理论上DownLoadFunction这个线程过程应是一个死循环,就象阻塞了一样,直到你需要它退出时才发一个exit message(由主线程发出)。
    例如:while(1){...};//但如果只是这样就会占用100%的CPU资源,因为程序一直在跑,没机会交回操作系统,这个死循环也太死了。
    因此就有了一个while(::GetMessage(&msg,NULL,0,0)){...};
    当中GetMessage就是交回操作系统处理,如果没有message,线程就被挂起,GetMessage不返回值给你,就象是你在等待操作系统回答,但操作系统死活都不理你,它干别的事去了。
    同样用WaitForSingleObjectcs或WaitForMultipObjectcs也能达到同样的效果。
      

  42.   

    补充:关于第3点当然,主线程也必须是一个"死"循环,要不程序也会有象第3点的问题。如果你的程序是基于SDK写的,你就要自己去写这个循环。
    如果你的程序是基于MFC写的,哪就不用担心,MFC已经帮你做了,其实如果把MFC框架展开,也会找到类似while(::GetMessage(&msg,NULL,0,0)){...}的语句。以上我所提到的"程序"只是指一般的程序,不包括组件,dll等特殊的程式
      

  43.   

    请 3236(Arcol) 大侠再看看:
    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;
    }
    最开始代码是这样的,程序可以执行,唯一 一个缺点是,主线程好象阻塞了,对话筐不能拖动。(我的本意是,让子线程执行下载,主线程控制下载线程的开始,暂停,停止),现在连主线程的对话筐都锁死了。
      

  44.   

    在回答前先得问你,程序是基于MFC写的吗?如果是的话你主线程依然是使用
    while (thread_finished_flag == FALSE){};吗?
    这和我所说的while(1){...};有什么区别?
    都是死循环,虽然有逃生机会,但也太死了吧。
    要注意,操作系统根本就没机会处理其它东西,你的对话框就别想动了。我看,你的思想是对的,但做法却错了,要记住,windows程序不再是过程程序,它是由事件驱动的。就说你的程序,线程控制下载线程的开始,暂停,停止是对的,但在同一个过程(函数)里面不应该同时处理子线程的“开始,暂停,停止”三个问题。你试着往对话框放3个按扭,分别表示“开始,暂停,停止”三个问题,然后在3个OnClick事件里分别处理这3个问题,你就会更清楚什么叫事件驱动了。在主线程中,一个事件(例如OnClick)响应后,应立即或尽快返回给系统(就是退出那个响应函数),而你呢?却一直在while()里头转!哪不是你在等操作系统,而是系统在等你啊!系统还有机会处理其它事件吗?另外,关于线程问题中,还有一个优先级问题,一般来说主线程要高于分线程,但所有线程都不应高于标准级,如非工程或驱动核心代码不能使用高优先级,默认就如此(莫非你改过?)。你可以烟酒烟酒。
      

  45.   

    已经开第2帖学基础知识了:
    请各位大侠指点
    http://expert.csdn.net/Expert/topic/1106/1106349.xml?temp=3.846377E-02
      

  46.   

    还有一点,我想知道
    pDownI->down.Download里头究竟在干嘛?
    是不是很复杂的?如果太复杂,这里会占用很多CPU资源的,尤其是在网络访问要等待时,而在等待时又不让系统干别的事,结果会导致子线程占用CPU过多,而令主线程没时间处理。所以有2点可以改进改进1.子线程也完全使用事件驱动的方式,就是借助WaitForMultipObjectcs等方法。
    2.适当降底子线程优先级。