zoukankan      html  css  js  c++  java
  • 关于delphi中多线程采用定时器的做法

    delphi中的提供了一个tthread的多线程类,开发者可以根据自身的需要,定制相应功能的多线程,而定时器在多线程中有很广泛的应用,在这里,只说关于waitforsingleobject来做定时器的一些关键问题。(关于定时器的相关知识,请阅读《深度历险》)
    waitforsingleobject是一个api函数,采用该函数,需要调用createevent,timesetevent,然后才能使用。但是这里使用到的event在线程中声明的位置不一样,效果也不一样,以下给出两种声明方式:
    unit PTUnit;

    interface

    uses
      Classes,mmsystem, Windows, sysutils, Forms;

    type
      TPingThread = class(TThread)
      private
        { Private declarations }
       {将event声明为该线程类的私有数据成员}
        timerid:integer;
        htimerevent:Thandle;
        fFileName: string;
      protected
        procedure Execute; override;
      public
        constructor create;
        procedure SetOver;
      published
      end;

    implementation

    constructor TPingThread.Create;
    begin
      FreeOnTerminate := true;
      Inherited Create(true);
    end;

    procedure TPingThread.SetOver;
    begin
      timerid := timesetevent(5,0,TFNTimecallback(htimerevent),0,time_periodic or time_callback_event_set);
    end;

    procedure TPingThread.Execute;
    begin
      htimerevent := CreateEvent(nil, False, False, nil);
      timerid := timesetevent(5*1000,0,TFNTimecallback(htimerevent),0,time_periodic or time_callback_event_set);
      repeat
        if WaitForSingleObject(htimerevent,INFINITE) = WAIT_OBJECT_0 then
        begin
          if Terminated then break;
          dosomething;
       end;
      until false;
      timekillevent(timerid);
      CloseHandle(htimerevent);
    end;
    end.
    这种声明方式保证了线程能够正常的执行。但是,下面一种声明方式就不行了,当你只是创建一个线程实例的时候,还能正常的执行,如果创建了两个以上的线程实例,那就不对了。
    unit PTUnit;

    interface

    uses
      Classes,mmsystem, Windows, sysutils, Forms;

    type
      TPingThread = class(TThread)
      private
        { Private declarations }
        fFileName: string;
      protected
        procedure Execute; override;
      public
        constructor create;
        procedure SetOver;
      published
      end;

    implementation
    {在实现部分声明事件}
    var
      timerid:integer;
      htimerevent:Thandle;

    constructor TPingThread.Create;
    begin
      FreeOnTerminate := true;
      Inherited Create(true);
    end;

    procedure TPingThread.SetOver;
    begin
      timerid := timesetevent(5,0,TFNTimecallback(htimerevent),0,time_periodic or time_callback_event_set);
    end;

    procedure TPingThread.Execute;
    begin
      htimerevent := CreateEvent(nil, False, False, nil);
      timerid := timesetevent(5*1000,0,TFNTimecallback(htimerevent),0,time_periodic or time_callback_event_set);
      repeat
        if WaitForSingleObject(htimerevent,INFINITE) = WAIT_OBJECT_0 then
        begin
          if Terminated then break;
          dosomething;
       end;
      until false;
      timekillevent(timerid);
      CloseHandle(htimerevent);
    end;
    end.
    以上两个除了事件声明位置不一样,其他功能均一样的代码在创建了两个以上线程实例的时候,第一个能够正常执行,第二个中的定时器的时间间隔就会出问题,而且当结束其中一个线程的时候,另外一个线程也无法正常工作。

    总结:建议使用第一种声明方式,这种方式能确保正常运行。

  • 相关阅读:
    CF1202F You Are Given Some Letters...
    CF1178E Archaeology
    PTA (Advanced Level) 1005 Spell It Right
    PTA (Advanced Level) 1004 Counting Leaves
    Qt5——从零开始的Hello World教程(Qt Creator)
    PTA (Advanced Level) 1003 Emergency
    PTA (Advanced Level) 1002 A+B for Polynomials
    HDU 1272 小希的迷宫
    FZU 2150 Fire Game
    HihoCoder
  • 原文地址:https://www.cnblogs.com/MaxWoods/p/1821216.html
Copyright © 2011-2022 走看看