一、线程的局部变量threadvar
- type
- TForm1 = class(TForm)
- Button1: TButton;
- Memo1: TMemo;
- procedure Button1Click(Sender: TObject);
- private
- { Private declarations }
- public
- { Public declarations }
- end;
- TMyThread=class(TThread)
- private
- FNewStr:string;
- protected
- procedure Execute;override;
- public
- constructor Create(const ANewStr:string);
- end;
- var
- Form1: TForm1;
- implementation
- {$R *.dfm}
- var
- n:integer;
- threadvar
- GlobalStr:string;
- procedure SetShowStr(const S:string;Memo:TMemo);
- begin
- if s='' then
- //MessageBox(0,pchar(GlobalStr),'The String is...',MB_OK)
- begin
- inc(n);
- Memo.Lines.Add(inttostr(n)+GlobalStr);
- end else GlobalStr:=S;
- end;
- constructor TMyThread.Create(const ANewStr: string);
- begin
- FNewStr:=ANewStr;
- Inherited Create(False);
- end;
- procedure TMyThread.Execute;
- begin
- FreeOnTerminate:=True; //终止后自动free
- SetShowStr(FnewStr, Form1.Memo1);
- SetShowStr('', Form1.Memo1);
- end;
- procedure TForm1.Button1Click(Sender: TObject);
- begin
- n:=1;
- SetShowStr('Hello World', Form1.Memo1); //Global:='Hello World'
- SetShowStr('', Form1.Memo1); //show 1Global
- TMyThread.Create('Mygodsos'); //Global:='Mygodsos',show 2Global
- Sleep(100);
- SetShowStr('', Form1.Memo1); //show 3Global
- end;
- 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)
- procedure TForm1.Button2Click(Sender: TObject);
- var
- MyThread1:TMyThread;
- MyThread2:TMyThread;
- begin
- n:=0;
- SetShowStr('Hello World',Form1.Memo1); //Global:='Hello World'
- SetShowStr('',Form1.Memo1); //show Global
- MyThread1:=TMyThread.Create('thread 1:'); //Global:='Mygodsos',show Global
- MyThread2:=TMyThread.Create('thread 2:'); //Global:='Mygodsos',show Global
- MyThread1.Resume;
- MyThread2.Resume;
- Sleep(100);
- SetShowStr('',Form1.Memo1); //show Global
- 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后,在主进程中先返回哪个线程是有一定的随机性的。但前面的序号还是一样的,意思是虽然主进程返回哪个线程的次序不一样,但线程执行的次序还是没变。不知道我这样理解对不对。