to zb_china(已经离开):
比如这样:
for(i=0;i<100;i++)
{
  ....
  AfxBeginThread(mythreadProc,(LPVOID)&myInfo);
  ....
}
如果这里的myInfo是全局变量的话,你在第i+1个的线程中改变了myInfo的值,对前面的i个线程就会产生影响。这当然是我所不希望的。

解决方案 »

  1.   

    我希望传给每一个mythreadProc的结构都是不一样的。
      

  2.   

    用new,线程进去就Copy内存到局部变量,然后马上delete,这样在99.99999%的情况下TerminateThread都不会造成问题。如果实在要追求完美,就用你所说的用Event来等待。至于如何为每一个工作者线程设置一个同步对象呢?我想没有必要吧?
    WaitForMultiObject的参数可以是一个线程句炳的数组,不需要用其他的同步对象了。另外,TerminateThread,不光造成new的内存不释放,还有分配的其他系统资源也不会释放的。
      

  3.   

    HANDLE threads[100];threads[0] = CreateThread(...);
    threads[1] = CreateThread(...);
    ......WaitForMultiObject( 100, threads, TRUE, INFINITE);
      

  4.   

    To plato(天天):
    你的WaitForMultiObjects(100, threads, TRUE, INFINITE); 确实能等到100个子线程都结束,但是问题是,用户要关闭一个进程,居然要等很长时间(如果该100个子线程非常慢的话),这是不可忍受的。
    所以还是要给那100个线程发送一个同步事件(event),告诉它们,你们可以退出循环或者当前的过程,赶快返回。这样是否每一个工作者线程都需要一个同步HANDLE了呢?(这个EVENT HANDLE实际上是由主线程发送给工作者线程的),所以我想每一个工作者线程还是需要一个同步HANDLE的(那样的话,不就是说N个子线程需要N个同步HANDLE对象么?),不知道兄台有什么观点?请指教。
      

  5.   

    首先设一个全局变量做线程计数,初始化时该变量为0;以后每个线程进入时对此值加1,退出时减一。另外再设一个全局变量做结束标志,初始化时为假;每个线程在内部不停监测这一标志,当为真时就退出。主线程结束时,首先点亮结束标志(令其为真),然后循环监测线程计数(当然,这里还可引入一些超时机制,以防万一),直至它为0时方可退出。
    由于对线程计数的访问必须是互斥的(各个线程都会对其读写),你可以在每个线程对其加减操作时使用互斥对象(Mutex)来实现。结束标志不存在冲突问题(各个线程都是读,只有主线程写),没有必要使用额外的技术。
      

  6.   

    其实在使用全局变量“结束标志”的情况下,上述的全局变量“线程计数”也完全可以不用。在主线程结束时可以先点亮结束标志,然后用WaitForMultipleObjects即可。这样做也省去了自己写代码处理超时的麻烦。但有一个缺点就是你必须在程序中维持一个线程句柄的列表,并随着线程的启动与终止不断更新。
      

  7.   

    那你先对每个线程PostThreadMessage( WM_QUIT ),比同步对象简单多了。
    然后再WaitForMultiObjects。
      

  8.   

    都有一些道理。只不过你们谁可以谈谈在线程中用全局变量和事件作为退出标志的优缺点?
    比如如下:
    ....
    for(i=0;i<N;i++)
    {
       .....
       if(g_bQuit)
         break;
       ....
    }
    也可以是:
    ....
    for(i=0;i<N;i++)
    {
       .....
       if(WaitForSingleObject(killEvent,0)==WAIT_OBJECT_0)
          break;   
    }
    这两种各有什么优缺点呢?另外,你们哪一个对线程池操作有研究,可以一起分析一下,如何?
      

  9.   

    g_bQuit简单一些,在这个例子中,WaitForSingleObject(killEvent)没什么优点。
      

  10.   

    plato(天天)说的对,我也是用线程内的局部变量记录下LPVOID后就将NEW 产生的堆DELETE掉。
    一般是不会出错的。
      

  11.   

    我觉得还是用局部变量。调用工作者线程的局部函数中用局部变量还是new无所谓。进入工作者线程后立即把该变量拷贝到局部变量中,这是就象对待一般函数中的局部变量一样了。剩下的问题其实就是如何用主线程控制子线程的结束的问题了。如果能保证主线程退出时它正常结束所有子线程,则没有泄露问题。
      

  12.   

    这样是绝对不安全的。
    void Doit()
    {
     struct Para para;
     CreateThread(..., &para);
    }一定要:
    void Doit()
    {
     struct Para * para ;
     CreateThread(..., para);
    }或者
     struct Para para;
    void Doit()
    {
     CreateThread(..., &para);
    }
      

  13.   

    听说工作者线程是没有消息循环的是这样吗?那么你给一个工作线程发消息他可以接收到吗?我觉得用公用变量作为线程退出的标志是挺方便的,就是别在线程处理函数中改变公用变量就行了。用事件的方式更有优势吧,你可以使用WaitForSingleObject函数使线程挂起,而不占用CPU循环,而且据说因为事件是内核对象还可以在进程之间进行同步。
      

  14.   

    同意AriDo的观点,程序员就是要做即使非常小的概率但是还是会发生的事情。