[关于超时] 一个简单的问题难道了无数高手=============================================================
  一个人正在跑步,这时候你命令他停下来,结果是这个人肯定会停下来.
问题是:如果他的一条腿还没有着地呢?
1: 保持一条腿还在空中在
2: 等待这条腿落地后立即停下来   在现实生活中这个人肯定会等待那条腿落地后才停下来 
那么在程序中是这样吗?
=============================================================  在window API中有些函数执行需要很长一段时间才返回结果
我们有时候需要在指定的时间内没有返回的话,就停止函数执行.一般我们可以用WaitForSingleObject来设置超时,
但是这个函数没有句柄啊?用WaitForSingleObject也许不行.
[如果你认为行,或者知道其它方法的人请指教]于是我想,把这个函数放在一个线程mythread中
function mythread
begin
  APIfun1;//比如这个API函数要30秒钟才能返回
  
  other code;
  ... ...
end;在主程序中,从CreatThread的时候开始计时;
如果到了指定的时间timeout没有放回结果的话,
就TerminateThread 终止线程那么现在问题就出现了:
我相信windows肯定会终止这个线程
但是这个线程是否要等待这个函数执行完毕后才终止呢?
这样说不知道大家明白了没有?
还没有明白的朋友请再次看前面的比喻.function mythread
//下面把线程函数分成三个部分看起来,更容易理解
begin
  //----------------------------------------------  //此时如果主程序终止线程,那么没有什么疑问;肯定会立即终止的,  //----------------------------------------------  APIfun1;  //比如这个API函数要60秒钟才能返回
     // 问题是APIfun1正在执行,是执行完毕后退出,还是立即退出???
  //----------------------------------------------  //此时如果主程序终止线程,那么没有什么疑问;肯定会立即终止的,  //---------------------------------------------  other code;  //------------------------------------------
  ... ...
end;
也许你要问,能不还具体一点?
好的我给个实际的API函数的例子你
function NetUse(ip):boolean;
var
  NRW: TNetResource; Res: Dword;
begin
  with NRW do
  begin
    dwType := RESOURCETYPE_ANY;
    lpRemoteName := pchar('\\'+ip+'\ipc$');
    lpLocalName := '';
    lpProvider := '';
  end;
  Res := WNetAddConnection2(NRW, '', '', 0);
  if Res = No_Error then result:=true  else result:=false;
end;===================================================
          仁者见仁,智者见智,请勿灌水.
===================================================

解决方案 »

  1.   

    就我所知, 沒有100% 安全的中止線程的方法, 如真如你說的;  APIfun1;//比如这个API函数要30秒钟才能返回那可能會引發不可預料的結果, 只不過, windows 的安全,穩定性現在做得比較好, 一般不會出嚴重的錯誤我一般的做法, 是在進入一個長時間運算前, 再測試判斷下有否結束的事件發生
      

  2.   

    thread1func()
      dwTime:=GetTickCount();
      APIFunc(handle,...)
    end;thread2func()/Timer
      if GetTickCount()-dwTime>overtime then
        closehandle(handle);  //APIFunc return;
      

  3.   

    这个应该是可以直接终止的
    你看Windows的进程管理器
    大家继续
    学习ing
      

  4.   

    终止是肯定会终止的,只不过是时间问题。
    楼主如果要硬行终止一个线程,可以用 TerminateThread() API 啊。
      

  5.   

    ==================================
    ==================================
    看了你们的解答;发现你们还没有明白我的意思
    关于如何计时和如何终止线程不是本问题的关键
    进程会不会终止也不是问题的关键
    TerminateThread进程肯定会终止的,这是没有任何疑问的!关键在于进程是马上结束这个API,还是等这个API运行完毕后在结束进程
    ==================================
                   请大家理解了题目再做回答!!!==================================
      

  6.   

    做个测试...
    在线程中用GetTickCount测试一个比较大的循环,然后比较正常结束线程所花的时间和用TerminateThread强行结束所花的时间...
      

  7.   

    应该不是马上中止的.这种例子常见于一些网络程序.如楼上所说,看看windows的任务管理器正好可以验证这一点。如果一个应用程序正在查找网络资源(或如获取网络邻居列表),这时在任务管理器中去中止它,是要等一段时间才会中止的.我最近写过一段用一个线程去遍历局域网资源的程序时,也遇到同样的问题.我认为,这不可避免!
      

  8.   

    到现在为止,只有singun(singun) 的回答没有跑题!我在此向您表示致敬!!!同时非常同意您的观点!但是我想TerminateThread这个API也许还可以分解为更小的元素能否直接直接调用更底层的代码????(若干年前人们说 分子 是最小的元素;现在人们发现了 原子)我认为只有知道了哪个更小的元素,才能从更本解决这个问题再次向singun(singun)致敬!!!(同时对mscrack的智商表示鄙视,严重鄙视)
      

  9.   

    Windows强制终止线程的时候,不会等待线程函数返回。他做这些事情确保安全,清理线程关联的系统对象(里面保存了线程运行被中断时的各个寄存器值),把线程从等待队列中取走,清理线程关联的窗口,清理他的消息队列,清理线程关联的堆栈Windows根本不关心线程处于什么状态,他活生生的把线程杀了,把线程的堆栈收回了,也就无所谓线程函数的返回了。Windows总能保证自己的完整性。
      

  10.   

    还有,线程在运行时打开的文件句柄,打开的系统对象,都不会在线程被强制终止的时候关闭。只有进程结束的时候,才会收回这个进程中打开的句柄。比如说,你在一个后备进程中打开了TCP的一个端口,但是你在主线程中强制结束了这个后备线程,那么这个被打开的端口直到进程结束或者程序的其他部分关闭它的时候才会得到关闭。
      

  11.   

    在这里我要感谢第二个人,就是 BlueTrees(蜗牛) 
    您的解答我很满意!但是我有个疑问:
    您开始说“Windows根本不关心线程处于什么状态,他活生生的把线程杀了,把线程的堆栈收回了”
    如果这样的话,线程应该马上终止;
    但是您后面又说“后备线程,直到进程结束或者程序的其他部分关闭它的时候才会得到关闭。”
    这么说线程还没有完全终止???
    是否有点自相矛盾?请您再次指点!谢谢
    ----------------------------------
    我又想到一个相关的问题:
    比如我们在编写多线程的时候
    如果线程超时就TerminateThread,并保持线程总数不超过制定数量(比如300)个
    如果TerminateThread不能保证真正的终止的化,
    那么我们设置的最大线程数就是自欺欺人!!!
    ----------------------------------
      

  12.   

    矛盾吗?嗬嗬问题在,这些对象都是和进程关联的,而不是线程,为什么这些对象和进程关联不和线程关连呢?考虑WinSock编成,有很多情况,是数个线程通过同一个端口句柄发送数据的,那么这样的对象要和任何一个线程关联都不合适。线程的堆栈和中断现场只和特定的线程相关,所以需要关联,窗口过程的消息要通过线程的消息循环来接收,所以必须和线程关联。进程维护的是内存空间隔离,线程则是调度使用CPU的。
      

  13.   

    多谢BlueTrees(蜗牛)的回答,这解释了我的一些疑惑。
      

  14.   

    我知道你的意思,你是说,网络数据发送了一半,强制结束线程会发生什么。发送数据,是不是要消耗CPU时间的,那么这个时间片是属于谁的呢?当然是和发送线程相关的。如果发送线程强制结束了,那么系统对象并没有消除,但是他也得不到时间片来继续发送数据了。上面说的是同步的情况。异步发送的时候,缓冲区数据的发送用的不是任何一个线程的时间,或者使用的是系统线程的时间,当然缓冲区没发送完毕,即便线程结束也不会停止,除非驱动程序觉得没必要发送了,这取决于驱动程序如何设计的了。
      

  15.   

    楼主的意思我明白了,其实写太多反而会让人误解你的意思。
    就是想知道一个线程如果在做需要很长时间才能结束的任务的话,当TerminateThread命令它终止时,是不是会马上终止。
    这个当然是马上终止的啊,不管它是在做一个for循环运算还是正处于它所调用的某个API里面,它都会马上终止的。因为TerminateThread是直接挂起线程,然后销毁线程的一切,不管它正在做什么。即使它正处于某个API里面,又怎么样呢?那个API或者说某个DLL的函数代码在内存里是“死”的啊,被这个线程运行了之后才“活”过来的,既然线程被CPU挂起了,当然就不会再向下运行任何语句。就像一个人在跑步,当他一条腿还在空中的时候,你把他的时间暂停了(就像恐龙特急克塞号),然后把他“销毁”了,他已经不存在了,他的腿还怎么落地呢?
      

  16.   

    “进程是马上结束这个API,还是等这个API运行完毕后在结束进程?”
    写个程序测试一下,看Windows是怎 么处理的。我想也不是绝对的,就是说有的线程会立即终止,但有的则不然,看Windows怎么处理了,如果这时Windows觉得产即结束他是安全的,那它就会这样做,否则可能会等待到一个安全时刻才结束。立即终止线程是不安全的。将造成无法预料的后果。估计WINDOWS会考虑到这一点,例如:根据当前线线程的内配分配情况来决定等。具体可以参考MSDN
      

  17.   

    可以参考:
    在Java的早期版本里面,提供了立即终止线程的方法(suspend(),stop())。
    但从Java2后,官方文档中强调,这样调用是不安全,不赞成这样处理,而有join()方法等待线程结束,这种方法被认为是安全的。
      

  18.   

    TerminateThread is used to cause a thread to exit. When this occurs, the target thread has no chance to execute any user-mode code and its initial stack is not deallocated. DLLs attached to the thread are not notified that the thread is terminating. 
    TerminateThread is a dangerous function that should only be used in the most extreme cases. You should call TerminateThread only if you know exactly what the target thread is doing, and you control all of the code that the target thread could possibly be running at the time of the termination. For example, TerminateThread can result in the following problems:· If the target thread owns a critical section, the critical section will not be released. 
    · If the target thread is executing certain kernel32 calls when it is terminated, the kernel32 state for the thread's process could be inconsistent. 
    · If the target thread is manipulating the global state of a shared DLL, the state of the DLL could be destroyed, affecting other users of the DLL. A thread cannot protect itself against TerminateThread, other than by controlling access to its handles. The thread handle returned by the CreateThread and CreateProcess functions has THREAD_TERMINATE access, so any caller holding one of these handles can terminate your thread.
    If the target thread is the last thread of a process when this function is called, the thread's process is also terminated. 
    The state of the thread object becomes signaled, releasing any other threads that had been waiting for the thread to terminate. The thread's termination status changes from STILL_ACTIVE to the value of the dwExitCode parameter. Terminating a thread does not necessarily remove the thread object from the system. A thread object is deleted when the last thread handle is closed.
      

  19.   

    除非不得已
    坚决反对使用terminatethread