◆delphi多线程编程之二 ◆(乌龙哈里2008-10-12)

delphi多线程编程之二 ◆(乌龙哈里2008-10-12

(调试环境:Delphi2007+WinXPsp3 例程:Tst_Thread2.dpr

一、线程的局部变量threadvar

  1. type
  2.   TForm1 = class(TForm)
  3.     Button1: TButton;
  4.     Memo1: TMemo;
  5.     procedure Button1Click(Sender: TObject);
  6.   private
  7.     { Private declarations }
  8.   public
  9.     { Public declarations }
  10.   end;
  11.   TMyThread=class(TThread)
  12.   private
  13.     FNewStr:string;
  14.   protected
  15.     procedure Execute;override;
  16.   public
  17.     constructor Create(const ANewStr:string);
  18.   end;
  19. var
  20.   Form1: TForm1;
  21. implementation
  22. {$R *.dfm}
  23. var
  24.   n:integer;
  25. threadvar
  26.   GlobalStr:string;
  27. procedure SetShowStr(const S:string;Memo:TMemo);
  28. begin
  29.   if s='' then
  30.     //MessageBox(0,pchar(GlobalStr),'The String is...',MB_OK)
  31.   begin
  32.     inc(n);
  33.     Memo.Lines.Add(inttostr(n)+GlobalStr);
  34.   end else  GlobalStr:=S;
  35. end;
  36. constructor TMyThread.Create(const ANewStr: string);
  37. begin
  38.   FNewStr:=ANewStr;
  39.   Inherited Create(False);
  40. end;
  41. procedure TMyThread.Execute;
  42. begin
  43.   FreeOnTerminate:=True; //终止后自动free
  44.   SetShowStr(FnewStr, Form1.Memo1);
  45.   SetShowStr('', Form1.Memo1);
  46. end;
  47. procedure TForm1.Button1Click(Sender: TObject);
  48. begin
  49.   n:=1;
  50.   SetShowStr('Hello World', Form1.Memo1);   //Global:='Hello World'
  51.   SetShowStr('', Form1.Memo1);    //show 1Global
  52.   TMyThread.Create('Mygodsos');  //Global:='Mygodsos',show 2Global
  53.   Sleep(100);
  54.   SetShowStr('', Form1.Memo1);  //show 3Global 
  55. end;
  56. end.

 

 

 

    GlobalStr 声明不同时,结果分别是:

Threadvar            var

1Hello World            1Hello World

3Hello World            3Mygodsos

2Mygodsos               2Mygodsos

 

Delphi利用关键字threadvar封装API线程局部存储。它能使你在第一个运行的线程中创建一个全局变量的拷贝。如果用ThreadVar声明变量,则在程序结束前必须手动释放其占用的空间(这个手动释放的问题不知道d2007解决没有?)

ps 我看到很多关于threadvar释放要 := ''的,若不是string类型的给如何释放?)

 

二、双线程看看Threadvar:

Execute()Create(False)改成Create(True)

  1. procedure TForm1.Button2Click(Sender: TObject);
  2. var
  3.   MyThread1:TMyThread;
  4.   MyThread2:TMyThread;
  5. begin
  6.   n:=0;
  7.   SetShowStr('Hello World',Form1.Memo1);   //Global:='Hello World'
  8.   SetShowStr('',Form1.Memo1);    //show Global
  9.   MyThread1:=TMyThread.Create('thread 1:');  //Global:='Mygodsos',show Global
  10.   MyThread2:=TMyThread.Create('thread 2:');  //Global:='Mygodsos',show Global
  11.   MyThread1.Resume;
  12.   MyThread2.Resume;
  13.   Sleep(100);
  14.   SetShowStr('',Form1.Memo1);  //show Global
  15. end;

GlobalStr 声明为不同,结果对比是:

Threadvar           Var

1Hello World            1Hello World

4Hello World            4thread 2:

2thread 1:              3thread 2:

3thread 2:              2thread 1:

 

这里出现一个十分有趣的问题,若sleep()位置不同,结果不一样。

MyThread1.Resume;

Sleep(100);

MyThread2.Resume;

//Sleep(100);

改成这样后,结果是:

Threadvar           Var

1Hello World            1Hello World

3Hello World            3thread 1:

2thread 1:              2thread 1:

4thread 2:              4thread 2:

 

留意一下前面的序号,似乎sleep()的作用比较奇怪。

 

三、Sleep()函数

Win32API过程Sleep()。此过程声明如下:

procedure Sleep(dwMilliseconds:DWORD); stdcall;

Sleep()过程用来告诉操作系统,当前的线程在参数dwMilliseconds指定的时间内不需要分配任何CPU时间。插入这个调用是使很多的任务在发生时,使执行哪个线程有一些随机性。通常,可以把参数dwMilliseconds设为0。尽管,这并没有使当前的线程真的“睡眠”,但它使操作系统把CPU时间分给了其他优先级相等或更高的线程。要小心Sleep()神秘的时间调整问题。Sleep()可能会使你的机器出现特别的问题。这种问题在另一台机器上可能无法再现。

    对上面的例子,改回以下,把global设成var声明:

MyThread1.Resume;

MyThread2.Resume;

Sleep(100);

 

执行几次,结果:

1Hello World        1Hello World

4thread 2:          4thread 2:

3thread 2:          2thread 1:

2thread 1:          3thread 2:

 

看来sleep后,在主进程中先返回哪个线程是有一定的随机性的。但前面的序号还是一样的,意思是虽然主进程返回哪个线程的次序不一样,但线程执行的次序还是没变。不知道我这样理解对不对。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值