代码很简单,就那么几行。
主要就是想看,线程是否 Sleep 了我设置的秒数,例如我代码写 Sleep(10),我就想看看 它是否真的睡了 10ms 。
代码如下:
Form:
unit Unit1;interfaceuses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls,
  MyThread;type
  TForm1 = class(TForm)
    Memo1: TMemo;
    Edit1: TEdit;
    Label1: TLabel;
    Button1: TButton;
    Button2: TButton;
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
  private
    FMyThread:TMyThread;
    procedure OnMY(var mesg:TMessage);message WM_MY;
  end;var
  Form1: TForm1;implementation{$R *.dfm}procedure TForm1.OnMY(var mesg:TMessage);//message WM_MY;
begin
  Memo1.Lines.Add(inttostr(mesg.LParam));
end;procedure TForm1.Button1Click(Sender: TObject);
begin
  if FMyThread=nil then
    FMyThread := TMyThread.Create(StrToInt(trim(Edit1.Text)) , self.Handle);
end;procedure TForm1.Button2Click(Sender: TObject);
begin
  if FMyThread<>nil then
    FreeAndNil(FMyThread);
end;end.
线程:
unit MyThread;interfaceuses
  Classes, Messages, Windows;const
  WM_MY = WM_USER + 100;type
  TMyThread = class(TThread)
  private
    FInterval:integer;
    FOwnerWND:THandle;    FTick1:integer;
    FTick2:integer;
  protected
    procedure Execute; override;
  public
    Constructor Create(const AInterval:integer;const AOwnerWND:THandle);
    destructor Destroy;override;
  end;implementation{ TMyThread }Constructor TMyThread.Create(const AInterval:integer;const AOwnerWND:THandle);
begin
  inherited Create(true);  FInterval:=AInterval;
  FOwnerWND:=AOwnerWND;  self.Resume;
end;destructor TMyThread.Destroy;//override;
begin
  self.Terminate;
  self.WaitFor;
  
  inherited;
end;procedure TMyThread.Execute;
begin
  while not self.Terminated do
  begin
    Sleep(FInterval);
    
    FTick2:=GetTickCount;
    PostMessage(FOwnerWND,WM_MY,0,FTick2-FTick1);
    FTick1:=FTick2;
  end;
end;end.
情况一:
机子里没开别的软件,我点击 Button1 ,一会后点击 Button2 ,结果如下图:看到基本 我设了 Sleep 5ms,但是 它睡了 15ms,我想应该是线程 时间片 的原因吧??-------(1)情况二:
我开了 PPStream 在看,然后运行 该程序,点击 Button1 一会后点击 Button2,结果如下图:这个我就有点想不通了,为什么是这样的结果??? ------ (2)请对上面两个问题(1)(2)进行解答,谢谢。PS:机子 P4 2.8 单核,XP pro sp2

解决方案 »

  1.   

    在多线程下用GetTickCount会不准确,操作系统会把CPU时间片分给其他进程,
    用 GetThreadTimes吧
      

  2.   

    这种测试很难达到精确的,你用postmessage也是有问题的,postmessage是进消息队列的,并不一定是实时处理的
      

  3.   

    LZ可能对Sleep有一个误解
    Sleep(X)的意思是使该线程放弃X毫秒的时间片的竞争
    当X毫秒过后,该线程醒来后,有了竞争时间片的权利,但这时很可能其它线程对CPU享有控制权。
    所以需要排队!
      

  4.   

    关于 放弃时间片 ,我知道。但是如下:
    procedure TMyThread.Execute;
    begin
      while not self.Terminated do
      begin
        Sleep(FInterval);  // 这里放弃时间片
        
        FTick2:=GetTickCount; //等到可以运行时,获得Tick数
        PostMessage(FOwnerWND,WM_MY,0,FTick2-FTick1); 
     //FTick2-FTick1 ---> 应该是这一次的GetTickCount,与上一次GetTickCount的时间差
        FTick1:=FTick2;
      end;
    end;
    我是不明白:在开了PPStream后,为何 "FTick2-FTick1" 会有 "0" 出现???
      

  5.   

    对于 "多线程下用GetTickCount会不准确" ,不太明白,我 Sleep 之后 调用 GetTickCount,应该是获得 "开机-->调用GetTickCount" 之间 的毫秒数,为何会不准?还有 GetThreadTimes 如何用啊? 我调用 GetThreadTimes 返回值<>0,但为何 后面3个参数(lpEXITTIME、lpKernelTime、lpusertime) 的返回值都是0???如何用它来达到我的要求(看看线程实际睡了多长时间)?
      

  6.   

    GetTickCount和Sleep,在当前的操作系统当中保证的精确度,最低是50毫秒,服务器版系统为15毫秒,在空闲的情况下,工作站基本上可以达到15毫秒左右的精度,服务器可以达到5毫秒的精度。
      

  7.   

    用GetTickCount只能精确到64分之一秒,用这个看看function GetCPUTimeCount: Int64;
    asm
      DB     $0F,   $31   //rdtsc
    end;var
      t1, t2: int64;
    begin
      t1 := GetCPUTimeCount;
      sleep(1);
      t2 := GetCPUTimeCount;
      //t1, t2再除以你的CPU主频,相减可以得到精确的时间
    end;
    另外,windows7下GetLocalTime精度可以到1毫秒
      

  8.   

    To ALL :我觉得不管 开不开 PPS,我线程里 Sleep(5) 或Sleep(10) 都应该是 睡了15ms,这里应该对吧??然而,我在机子空闲的情况下,得到了正确的值 --> 睡了15ms
    但是,在开了 PPS 后却,得到了不正确的值 --> 睡了 小于 15ms现在问题就是:如何在 开PPS 的情况下,得到正确的值???
      

  9.   


    用了这个方式,代码改为:function GetCPUTimeCount: Int64;
    asm
      DB $0F, $31 //rdtsc
    end;procedure TMyThread.Execute;
    var timePoint1:TDatetime;
        timePoint2:TDatetime;
        passTime:Int64;    i,j:integer;
        Tick1:integer;
        Tick2:integer;    t1, t2: int64;
        t:integer;
    begin
      while not self.Terminated do
      begin
    //{
        t1 := GetCPUTimeCount;
        sleep(FInterval);
        t2 := GetCPUTimeCount;
        //t1, t2再除以你的CPU主频,相减可以得到精确的时间
        t:=(t2-t1) div 2800000;
        PostMessage(FOwnerWND,WM_MY,0,t);
    //}
      end;
    end;
    机子空闲时,如下图:
    开PPS后,如图:
    Sleep(1) 和 Sleep(5) 得到的结果 都小于15ms,这个结果应该是不对的吧??
      

  10.   

    应该是精度的问题
    你的第一个例子,如果把sleep 5 改成 50,应该可以看到偏差,不会是0
      

  11.   

    我希望看到的结果是:开PPS 和 不开PPS , Memo1 输出的结果一样。应如何做?楼顶的代码,50ms,结果如下:
    不开PPS:开PPS:
      

  12.   

    所谓精度,是一个最小保障精度,但并不是结果。Sleep实际是有在执行操作的,实际上如果系统空闲的话是可以达到精度要求的,但是忙的时候是无法保障的。对于GetTickCount则跟系统的采样精度有关。由于PPStream等类似软件使用了多媒体定时器,并且会修改系统的时钟精度,因此会导致Sleep的计时精度增加。但是GetTickCount的采样频率并没有改变,因此就存在了误差。
      

  13.   

    to unsigned :不太明白...
    timeBeginPeriod、timeEndPeriod、timeSetEvent、timeKillEvent这几个函数,貌似是用来做毫秒级定时器的。
    如何用它们 来达到我的要求(看 线程到底 睡了多久)???
      

  14.   

    从线程睡着开始,用 timeEndPeriod 的回调函数,每ms都检查线程是否醒来?这样做???
      

  15.   

    使用GetTickCount函数来记录一个起始点和一个结束点,相减就得出Sleep的时间了。
      

  16.   

    在这里我想请教下,如果主进程生成了一个 createthread后,再sleep(x),会对在运行中的thread有影响吗?1》 
    2》
    3》
    4》createthread(...) 假如这个线程要运行10秒
    5》sleep(x)此时主线程sleep了,会对已在运行中thread有影响吗?
      

  17.   

    我有個程序,用sleep(1)有時卻延遲了10S,鬱悶啊!
      

  18.   

    ppstream 使用了多媒体时钟,精确度高了。