delphi里面我想用线程调用某个函数(这个函数在某个.pas文件里面写好了),该函数是一个1000次的循环,我想用线程调用100次后该线程被挂起,然后通知下一个函数执行。
现有如下问题:1、我如何创建一个线程
              2、线程执行到100次此后(线程还没有执行完)如何通知下一个函数执行

解决方案 »

  1.   

    Windows 95 是Microsoft 公司的第一个真正的多任务操作系统。在每一时刻可以
    有多个进 程同时工作,而每一个进程又包含有多个线程。但只有一个处理
    器的计算机不可能真正地“ 同时”执行多个线程,而是操作系统把时间分成
    若干个时间片,然后把一个个时间片分配给 每一个线程。 ---- 一个执行了的程序就是一个进程,一个进程则至少有一个主线程。一位
    高级程序 员,绝不会让自己的程序里面只有一个主线程存在(除非只有很
    少的几十行代码),而是尽量 让自己的程序在同一时刻里干更多的事,在
    比较大一点的应用中尤其如此,象数据库应用程 序,在统计的时候我还想
    做其他事呢!因此,如何有效地利用线程则是每一个程序员都应了 解的。
    本文就此简单地谈一下在Delphi 中如何利用线程。 ---- ( 一) 当使用线程时,我们主要有两个任务: ---- (1)创建一个线程。 ---- (2)创建一个能作为线程入口的函数。 ---- Windows API 调用CreateThread 函数来创建一个线程。函数如下: HANDLE CreateThread(LPSECURITY_
    ATTRIBUTES  lpThreadAttributes,
    //线程安全属性地址
      DWORD  dwStackSize,
      //初始化线程堆栈尺寸
      LPTHREAD_START_ROUTINE  lpStartAddress,
      //线程函数所指向的地址
         LPVOID  lpParameter,
      //给线程函数传递的参数
      DWORD  dwCreationFlags,
      //有关线程的标志
      LPDWORD  lpThreadId
      //系统分配给线程的ID 
         );
    ---- 第一个参数是安全属性,一般设为nil,使用缺省的安全属性。当我们想此
    线程有另外的子进 程时,可改变它的属性。 ---- 第二个参数是线程堆栈尺寸,一般设为0,表示与此应用的堆栈尺寸相
    同,即主线程 与创建的线程一样长度的堆栈。并且其长度会根据需要自动
    变长。 ---- 第三个参数,也是最重要的一个,是一个指向函数名的指针,但传递时
    很简单,只需 在线程函数名前加上@ 就可以了。 ---- 第四个参数是你需要向线程函数传递的参数,一般是一个指向结构的指
    针。不需传 递参数时,则这个参数设为nil。 ---- 第五个参数,传入与线程有关的一些标志,如果是CREATE_SUSPENDED, 则创建
    一个 挂起的线程,即这个线程本身已创建,它的堆栈也已创建。但这个线
    程不会被分配给CPU 时 间,只有当ResumeThread 函数被调用后才能执行;当然,
    也可以调用SuspendThread 函数再次 挂起线程。要是标志为0,那么一旦建立线
    程,线程函数就被立即调用。一般传为0 即可。 ---- 最后一个参数是系统分配给这个线程的唯一的ID 标志。 ---- 下面这个程序MyThreadPro.pas 介绍了线程如何建立及使用: //Your first test Thread Program.
    unit MyThreadPro;
    interface
    uses
      Windows, Messages, SysUtils, Classes, 
    Graphics, Controls, Forms, Dialogs,
      StdCtrls;
    type
      TForm1 = class(TForm)
        UsedThread: TButton;
        NoUsedThread: TButton;
        procedure UsedThreadClick(Sender: TObject);
        procedure NoUsedThreadClick(Sender: TObject);
    var
      Form1: TForm1;
    implementation
    {$R *.DFM}
    //这是线程函数,
    它可以放在下面程序的任何地方
    function MyThreadFunc(P:pointer):Longint;stdcall;
    var
       i:integer;
       DC:HDC;
       S:string;
    begin
         DC:=GetDC(Form1.Handle);
         for i:=0 to 100000 do begin
             S:=Inttostr(i);
             Textout(DC,10,10,Pchar(S),length(S));
         end;
         ReleaseDC(Form1.Handle,DC);
    end;
    procedure TForm1.UsedThreadClick(Sender: TObject);
    var
       hThread:Thandle;//定义一个句柄
       ThreadID:DWord;
    begin
    //创建线程,同时线程函数被调用
    hthread:=CreateThread(nil,0,@MyThreadfunc,nil,0,ThreadID);
         if hThread=0 then
    messagebox(Handle,'Didn’t Create a Thread',nil,MB_OK);
    end;
    procedure TForm1.NoUsedThreadClick(Sender: TObject);
    begin
         MyThreadfunc(nil); 
    //没有创建线程时,直接调用线程函数
    end;
    end.
    ---- 上面这个程序介绍了我们在使 用线程及未使用线程二种情况下,运行该
    程序的反应。当点UsedThread 按钮时,则建立一个 线程,这时我们可以在程序
    进行计算的同时,改变窗体的尺寸及移动它。当按 下NoUsedThread 按钮时,不
    建立线程,我们会发现在程序没有计算完之前根本不能做其它任 何事情!
    此程序在基于Windows 95 的Delphi 3 中运行通过。 
      

  2.   

    (这些东西只是转载,不代表我个人的意思)
    你的第二个问题好像就是线程同步吧
    1. 信号灯对象    信号灯对象维持一个从0到指定最大值之间的数。在其计数大于0时是有信号的,而在其计数为0时是无信号的。信号灯对象可用来限制对共享资源进行访问的线程数量,例如应用程序可使用信号灯对象来限制它建立的窗口数量。    用类的Create方法来建立信号灯对象,在调用该方法时,可以指定对象的初始计数和最大计数。该方法有四个参数,依次为:安全属性、初始计数、最大计数和对象名字(以便别的进程的线程可打开指定名字的信号灯句柄)。如:    Semaphore := TSemaphore.Create(nil,10,10,'');    一般把信号灯的初始计数设置成最大值。每次当信号灯有信号并等待函数返回时,信号灯计数就会减1,而通过调用对象的Release方法可按指定量增加信号灯的计数(默认为加1)。计数值越小就表明访问共享资源的程序越多。如:“Semaphore.Release(3, nil);”,其中第一个参数为增加的信号灯数量,第二个参数为执行该方法之前的信号灯数量。信号灯用法举例:    if wrSignaled = Semaphore.WaitFor(10000) then//若信号灯是有信号的    begin     //打开另一个窗口    end     Semaphore.Release()    在线程建立窗口之前,它使用WaitFor函数确定信号灯的当前计数是否允许建立新的窗口,等待时间设为10秒。    2. 互斥对象    Mutex对象的状态在它不被任何线程拥有时是有信号的,而当它被拥有时则是无信号的。Mutex对象很适合用来协调多个线程对共享资源的互斥访问(mutually exclusive)。例如,有几个线程共享对数据库的访问时,线程可以使用Mutex对象,一次只允许一个线程向数据库写入。    用类的Create方法建立Mutex 对象,在建立Mutex 时,可以为对象起个名字,这样其他进程中的线程可以打开指定名字的Mutex对象句柄。例如:    Mutex := TMutex.Create(nil, False, '');    在完成对共享资源的访问后,可以调用Release方法来释放Mutex,以便让别的线程能访问共享资源。如果线程终止而不释放Mutex,则认为该Mutex被废弃。    互斥对象用法举例如下:    if wrSignaled = Mutex.WaitFor(10000) then//若获得互斥对象的拥有权     begin     try     //往数据库写入     finally    Mutex.Release;//释放对互斥对象的拥有权     end;     end;