delphi多线程编程3
窗体文件:object Form1: TForm1
Left = 0
Top = 0
Caption = 'Form1'
ClientHeight = 140
ClientWidth = 192
Color = clBtnFace
Font.Charset = DEFAULT_CHARSET
Font.Color = clWindowText
Font.Height = -11
Font.Name = 'Tahoma'
Font.Style = []
OldCreateOrder = False
OnCreate = FormCreate
Left = 0
Top = 0
Caption = 'Form1'
ClientHeight = 140
ClientWidth = 192
Color = clBtnFace
Font.Charset = DEFAULT_CHARSET
Font.Color = clWindowText
Font.Height = -11
Font.Name = 'Tahoma'
Font.Style = []
OldCreateOrder = False
OnCreate = FormCreate
PixelsPerInch = 96
TextHeight = 13
object Button1: TButton
Left = 109
Top = 107
Width = 75
Height = 25
Caption = 'Button1'
TabOrder = 0
OnClick = Button1Click
end
object Edit1: TEdit
Left = 109
Top = 80
Width = 75
TextHeight = 13
object Button1: TButton
Left = 109
Top = 107
Width = 75
Height = 25
Caption = 'Button1'
TabOrder = 0
OnClick = Button1Click
end
object Edit1: TEdit
Left = 109
Top = 80
Width = 75
Height = 21
TabOrder = 1
Text = 'Edit1'
OnKeyPress = Edit1KeyPress
end
end
再用 SyncObjs 单元下的 TSemaphore 类实现一次, 使用方法差不多, 运行效果也一样:unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;
type
TForm1 = class(TForm)
TabOrder = 1
Text = 'Edit1'
OnKeyPress = Edit1KeyPress
end
end
再用 SyncObjs 单元下的 TSemaphore 类实现一次, 使用方法差不多, 运行效果也一样:unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;
type
TForm1 = class(TForm)
Button1: TButton;
Edit1: TEdit;
procedure Button1Click(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
procedure Edit1KeyPress(Sender: TObject; var Key: Char);
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
uses SyncObjs;
var
f: Integer;
MySemaphore: TSemaphore;
Edit1: TEdit;
procedure Button1Click(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
procedure Edit1KeyPress(Sender: TObject; var Key: Char);
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
uses SyncObjs;
var
f: Integer;
MySemaphore: TSemaphore;
function MyThreadFun(p: Pointer): DWORD; stdcall;
var
i,y: Integer;
begin
Inc(f);
y := 20 * f;
if MySemaphore.WaitFor(INFINITE) = wrSignaled then
begin
for i := 0 to 1000 do
begin
Form1.Canvas.Lock;
Form1.Canvas.TextOut(20, y, IntToStr(i));
Form1.Canvas.Unlock;
Sleep(1);
end;
var
i,y: Integer;
begin
Inc(f);
y := 20 * f;
if MySemaphore.WaitFor(INFINITE) = wrSignaled then
begin
for i := 0 to 1000 do
begin
Form1.Canvas.Lock;
Form1.Canvas.TextOut(20, y, IntToStr(i));
Form1.Canvas.Unlock;
Sleep(1);
end;
end;
MySemaphore.Release;
Result := 0;
end;
procedure TForm1.Button1Click(Sender: TObject);
var
ThreadID: DWORD;
begin
if Assigned(MySemaphore) then MySemaphore.Free;
MySemaphore := TSemaphore.Create(nil, StrToInt(Edit1.Text), 5, '');
Self.Repaint;
f := 0;
CreateThread(nil, 0, @MyThreadFun, nil, 0, ThreadID);
CreateThread(nil, 0, @MyThreadFun, nil, 0, ThreadID);
CreateThread(nil, 0, @MyThreadFun, nil, 0, ThreadID);
MySemaphore.Release;
Result := 0;
end;
procedure TForm1.Button1Click(Sender: TObject);
var
ThreadID: DWORD;
begin
if Assigned(MySemaphore) then MySemaphore.Free;
MySemaphore := TSemaphore.Create(nil, StrToInt(Edit1.Text), 5, '');
Self.Repaint;
f := 0;
CreateThread(nil, 0, @MyThreadFun, nil, 0, ThreadID);
CreateThread(nil, 0, @MyThreadFun, nil, 0, ThreadID);
CreateThread(nil, 0, @MyThreadFun, nil, 0, ThreadID);
CreateThread(nil, 0, @MyThreadFun, nil, 0, ThreadID);
CreateThread(nil, 0, @MyThreadFun, nil, 0, ThreadID);
end;
{让 Edit 只接受 1 2 3 4 5 五个数}
procedure TForm1.Edit1KeyPress(Sender: TObject; var Key: Char);
begin
if not CharInSet(Key, ['1'..'5']) then Key := #0;
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
Edit1.Text := '1';
end;
procedure TForm1.FormDestroy(Sender: TObject);
begin
if Assigned(MySemaphore) then MySemaphore.Free;
CreateThread(nil, 0, @MyThreadFun, nil, 0, ThreadID);
end;
{让 Edit 只接受 1 2 3 4 5 五个数}
procedure TForm1.Edit1KeyPress(Sender: TObject; var Key: Char);
begin
if not CharInSet(Key, ['1'..'5']) then Key := #0;
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
Edit1.Text := '1';
end;
procedure TForm1.FormDestroy(Sender: TObject);
begin
if Assigned(MySemaphore) then MySemaphore.Free;
end;
end.
end.
多线程编程(13) - 多线程同步之 Event (事件对象)。
据说 Event(事件对象) 是多线程最原始的同步手段, 我觉得它是最灵活的一个.
Event 对象(的句柄表)中主要有两个布尔变量, 从它的建立函数中可以看得清楚:
function CreateEvent(
lpEventAttributes: PSecurityAttributes; {安全设置}
bManualReset: BOOL; {第一个布尔}
bInitialState: BOOL; {第二个布尔}
lpName: PWideChar {对象名称}
): THandle; stdcall; {返回对象句柄}
//第一个布尔为 False 时, 事件对象控制一次后将立即重置(暂停); 为 True 时可手动暂停.
//第二个布尔为 False 时, 对象建立后控制为暂停状态; True 是可运行状态.
和其他同类相比, 它的灵活性在于可随时 "启动运行"(SetEvent) 和 "暂停运行"(ResetEvent);
甚至还有个 PulseEvent 函数, 能控制执行一次后立即暂停, 很是方便.
本例效果图:
据说 Event(事件对象) 是多线程最原始的同步手段, 我觉得它是最灵活的一个.
Event 对象(的句柄表)中主要有两个布尔变量, 从它的建立函数中可以看得清楚:
function CreateEvent(
lpEventAttributes: PSecurityAttributes; {安全设置}
bManualReset: BOOL; {第一个布尔}
bInitialState: BOOL; {第二个布尔}
lpName: PWideChar {对象名称}
): THandle; stdcall; {返回对象句柄}
//第一个布尔为 False 时, 事件对象控制一次后将立即重置(暂停); 为 True 时可手动暂停.
//第二个布尔为 False 时, 对象建立后控制为暂停状态; True 是可运行状态.
和其他同类相比, 它的灵活性在于可随时 "启动运行"(SetEvent) 和 "暂停运行"(ResetEvent);
甚至还有个 PulseEvent 函数, 能控制执行一次后立即暂停, 很是方便.
本例效果图:
代码文件:unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;
type
TForm1 = class(TForm)
Button1: TButton;
Button2: TButton;
Button3: TButton;
Button4: TButton;
Button5: TButton;
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
procedure Button3Click(Sender: TObject);
procedure Button4Click(Sender: TObject);
procedure Button5Click(Sender: TObject);
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
var
Button5: TButton;
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
procedure Button3Click(Sender: TObject);
procedure Button4Click(Sender: TObject);
procedure Button5Click(Sender: TObject);
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
var
f: Integer; {用这个变量协调一下各线程输出的位置}
hEvent: THandle; {事件对象的句柄}
function MyThreadFun(p: Pointer): DWORD; stdcall;
var
i,y: Integer;
begin
Inc(f);
y := 20 * f;
for i := 0 to 200000 do
begin
if WaitForSingleObject(hEvent, INFINITE) = WAIT_OBJECT_0 then
begin
Form1.Canvas.Lock;
Form1.Canvas.TextOut(20, y, IntToStr(i));
Form1.Canvas.Unlock;
hEvent: THandle; {事件对象的句柄}
function MyThreadFun(p: Pointer): DWORD; stdcall;
var
i,y: Integer;
begin
Inc(f);
y := 20 * f;
for i := 0 to 200000 do
begin
if WaitForSingleObject(hEvent, INFINITE) = WAIT_OBJECT_0 then
begin
Form1.Canvas.Lock;
Form1.Canvas.TextOut(20, y, IntToStr(i));
Form1.Canvas.Unlock;
end;
end;
Result := 0;
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
Repaint; f := 0;
CloseHandle(hEvent); {如果已经创建过}
hEvent := CreateEvent(nil, True, True, nil);
end;
{创建线程}
procedure TForm1.Button2Click(Sender: TObject);
var
ThreadID: DWORD;
begin
end;
Result := 0;
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
Repaint; f := 0;
CloseHandle(hEvent); {如果已经创建过}
hEvent := CreateEvent(nil, True, True, nil);
end;
{创建线程}
procedure TForm1.Button2Click(Sender: TObject);
var
ThreadID: DWORD;
begin
CreateThread(nil, 0, @MyThreadFun, nil, 0, ThreadID);
end;
{暂停}
procedure TForm1.Button3Click(Sender: TObject);
begin
ResetEvent(hEvent);
end;
{启动}
procedure TForm1.Button4Click(Sender: TObject);
begin
SetEvent(hEvent);
end;
{启动后执行一次立即暂停}
procedure TForm1.Button5Click(Sender: TObject);
begin
end;
{暂停}
procedure TForm1.Button3Click(Sender: TObject);
begin
ResetEvent(hEvent);
end;
{启动}
procedure TForm1.Button4Click(Sender: TObject);
begin
SetEvent(hEvent);
end;
{启动后执行一次立即暂停}
procedure TForm1.Button5Click(Sender: TObject);
begin
PulseEvent(hEvent);
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
Button1.Caption := '创建 Event 对象';
Button2.Caption := '创建线程';
Button3.Caption := 'ResetEvent';
Button4.Caption := 'SetEvent';
Button5.Caption := 'PulseEvent';
end;
procedure TForm1.FormDestroy(Sender: TObject);
begin
CloseHandle(hEvent);
end;
end.
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
Button1.Caption := '创建 Event 对象';
Button2.Caption := '创建线程';
Button3.Caption := 'ResetEvent';
Button4.Caption := 'SetEvent';
Button5.Caption := 'PulseEvent';
end;
procedure TForm1.FormDestroy(Sender: TObject);
begin
CloseHandle(hEvent);
end;
end.
窗体文件:object Form1: TForm1
Left = 0
Top = 0
Caption = 'Form1'
ClientHeight = 149
ClientWidth = 228
Color = clBtnFace
Font.Charset = DEFAULT_CHARSET
Font.Color = clWindowText
Font.Height = -11
Font.Name = 'Tahoma'
Font.Style = []
OldCreateOrder = False
OnCreate = FormCreate
PixelsPerInch = 96
Left = 0
Top = 0
Caption = 'Form1'
ClientHeight = 149
ClientWidth = 228
Color = clBtnFace
Font.Charset = DEFAULT_CHARSET
Font.Color = clWindowText
Font.Height = -11
Font.Name = 'Tahoma'
Font.Style = []
OldCreateOrder = False
OnCreate = FormCreate
PixelsPerInch = 96
TextHeight = 13
object Button1: TButton
Left = 8
Top = 116
Width = 129
Height = 25
Caption = 'Button1'
TabOrder = 0
OnClick = Button1Click
end
object Button3: TButton
Left = 143
Top = 12
Width = 75
Height = 25
object Button1: TButton
Left = 8
Top = 116
Width = 129
Height = 25
Caption = 'Button1'
TabOrder = 0
OnClick = Button1Click
end
object Button3: TButton
Left = 143
Top = 12
Width = 75
Height = 25
Caption = 'Button3'
TabOrder = 1
OnClick = Button3Click
end
object Button4: TButton
Left = 143
Top = 43
Width = 75
Height = 25
Caption = 'Button4'
TabOrder = 2
OnClick = Button4Click
end
object Button5: TButton
Left = 143
TabOrder = 1
OnClick = Button3Click
end
object Button4: TButton
Left = 143
Top = 43
Width = 75
Height = 25
Caption = 'Button4'
TabOrder = 2
OnClick = Button4Click
end
object Button5: TButton
Left = 143
Top = 74
Width = 75
Height = 25
Caption = 'Button5'
TabOrder = 3
OnClick = Button5Click
end
object Button2: TButton
Left = 143
Top = 116
Width = 75
Height = 25
Caption = 'Button2'
TabOrder = 4
OnClick = Button2Click
Width = 75
Height = 25
Caption = 'Button5'
TabOrder = 3
OnClick = Button5Click
end
object Button2: TButton
Left = 143
Top = 116
Width = 75
Height = 25
Caption = 'Button2'
TabOrder = 4
OnClick = Button2Click
end
end
end
和前面一样, 再用 SyncObjs 单元下的 TEvent 类实现一次; 不过它没有实现类似 PulseEvent 的功能:unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;
type
TForm1 = class(TForm)
Button1: TButton;
Button2: TButton;
Button3: TButton;
Button4: TButton;
Button5: TButton;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;
type
TForm1 = class(TForm)
Button1: TButton;
Button2: TButton;
Button3: TButton;
Button4: TButton;
Button5: TButton;
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
procedure Button3Click(Sender: TObject);
procedure Button4Click(Sender: TObject);
procedure Button5Click(Sender: TObject);
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
uses SyncObjs;
var
f: Integer;
procedure FormDestroy(Sender: TObject);
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
procedure Button3Click(Sender: TObject);
procedure Button4Click(Sender: TObject);
procedure Button5Click(Sender: TObject);
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
uses SyncObjs;
var
f: Integer;
MyEvent: TEvent;
function MyThreadFun(p: Pointer): DWORD; stdcall;
var
i,y: Integer;
begin
Inc(f);
y := 20 * f;
for i := 0 to 200000 do
begin
if MyEvent.WaitFor(INFINITE) = wrSignaled then
begin
Form1.Canvas.Lock;
Form1.Canvas.TextOut(20, y, IntToStr(i));
Form1.Canvas.Unlock;
end;
function MyThreadFun(p: Pointer): DWORD; stdcall;
var
i,y: Integer;
begin
Inc(f);
y := 20 * f;
for i := 0 to 200000 do
begin
if MyEvent.WaitFor(INFINITE) = wrSignaled then
begin
Form1.Canvas.Lock;
Form1.Canvas.TextOut(20, y, IntToStr(i));
Form1.Canvas.Unlock;
end;
end;
Result := 0;
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
Repaint; f := 0;
if Assigned(MyEvent) then MyEvent.Free;
MyEvent := TEvent.Create(nil, True, True, '');
end;
{创建线程}
procedure TForm1.Button2Click(Sender: TObject);
var
ThreadID: DWORD;
begin
CreateThread(nil, 0, @MyThreadFun, nil, 0, ThreadID);
Result := 0;
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
Repaint; f := 0;
if Assigned(MyEvent) then MyEvent.Free;
MyEvent := TEvent.Create(nil, True, True, '');
end;
{创建线程}
procedure TForm1.Button2Click(Sender: TObject);
var
ThreadID: DWORD;
begin
CreateThread(nil, 0, @MyThreadFun, nil, 0, ThreadID);
end;
{暂停}
procedure TForm1.Button3Click(Sender: TObject);
begin
MyEvent.ResetEvent;
end;
{启动}
procedure TForm1.Button4Click(Sender: TObject);
begin
MyEvent.SetEvent;
end;
{启动后执行一次立即暂停}
procedure TForm1.Button5Click(Sender: TObject);
begin
ShowMessage('TEvent 类没有提供这个功能'); {我试过用 PulseEvent(MyEvent.Handle)
{暂停}
procedure TForm1.Button3Click(Sender: TObject);
begin
MyEvent.ResetEvent;
end;
{启动}
procedure TForm1.Button4Click(Sender: TObject);
begin
MyEvent.SetEvent;
end;
{启动后执行一次立即暂停}
procedure TForm1.Button5Click(Sender: TObject);
begin
ShowMessage('TEvent 类没有提供这个功能'); {我试过用 PulseEvent(MyEvent.Handle)
也不行}
end;
procedure TForm1.FormCreate(Sender: TObject);
waitforsingleobject函数begin
Button1.Caption := '创建 Event 对象';
Button2.Caption := '创建线程';
Button3.Caption := 'ResetEvent';
Button4.Caption := 'SetEvent';
Button5.Caption := 'PulseEvent';
end;
procedure TForm1.FormDestroy(Sender: TObject);
begin
MyEvent.Free;
end;
end.
end;
procedure TForm1.FormCreate(Sender: TObject);
waitforsingleobject函数begin
Button1.Caption := '创建 Event 对象';
Button2.Caption := '创建线程';
Button3.Caption := 'ResetEvent';
Button4.Caption := 'SetEvent';
Button5.Caption := 'PulseEvent';
end;
procedure TForm1.FormDestroy(Sender: TObject);
begin
MyEvent.Free;
end;
end.
多线程编程(14) - 多线程同步之 WaitableTimer (等待定时器对象)。
function CreateWaitableTimer(
lpTimerAttributes: PSecurityAttributes; {安全}
bManualReset: BOOL; {True: 可调度多个线程; False: 只调度一个线程}
lpTimerName: PWideChar {名称}
): THandle; stdcall; {返回句柄}
function SetWaitableTimer(
hTimer: THandle; {句柄}
var lpDueTime: TLargeInteger; {起始时间}
lPeriod: Longint; {间隔时间}
pfnCompletionRoutine: TFNTimerAPCRoutine;{回调函数的指针}
lpArgToCompletionRoutine: Pointer; {给回调函数的参数}
fResume: BOOL {是否唤醒系统}
): BOOL; stdcall; {}
function CreateWaitableTimer(
lpTimerAttributes: PSecurityAttributes; {安全}
bManualReset: BOOL; {True: 可调度多个线程; False: 只调度一个线程}
lpTimerName: PWideChar {名称}
): THandle; stdcall; {返回句柄}
function SetWaitableTimer(
hTimer: THandle; {句柄}
var lpDueTime: TLargeInteger; {起始时间}
lPeriod: Longint; {间隔时间}
pfnCompletionRoutine: TFNTimerAPCRoutine;{回调函数的指针}
lpArgToCompletionRoutine: Pointer; {给回调函数的参数}
fResume: BOOL {是否唤醒系统}
): BOOL; stdcall; {}
WaitableTimer 对象较复杂, 其基本的理念是让等候的线程在指定的时间运行.
像其他同类对象一样, 先要建立(CreateWaitableTimer), 建立函数的第二个参数决定是调度一个线程还是所有等候的线程; 这一点和信号对象(Semaphore) 有些类似, 不过 Semaphore 可以指定可驱动线程的具体数目.
和其他同类对象不同的是: 在 CreateWaitableTimer 以后, WaitableTimer 对象并没有马上开始工作;
再调用 SetWaitableTimer 函数后才能让它发挥作用. 这又有点像 Event 对象.
SetWaitableTimer 函数比较麻烦, 得慢慢来, 譬如这样使用:
var
hWaitableTimer: THandle; {WaitableTimer 对象的句柄变量应该是全局的}
procedure TForm1.Button1Click(Sender: TObject);
var
DueTime: Int64;
begin
{建立 WaitableTimer 对象并返回句柄}
hWaitableTimer := CreateWaitableTimer(nil, True, nil); {中间的 True 表示可驱动多个线程}
DueTime := 0; {这将是 SetWaitableTimer 的第二个参数; 因为是 var 参数, 不能直接给常量}
SetWaitableTimer(hWaitableTimer, {WaitableTimer 对象的句柄}
DueTime, {起始时间, 这里给的是 0}
0, {间隔时间, 这里给的也是 0}
nil, {暂不用回调函数}
nil, {当然也不需要给回调函数参数了}
False {此值若是 True, 即使系统在屏保或待机状态, 时间一到线程和系统将都被唤醒!}
procedure TForm1.Button1Click(Sender: TObject);
var
DueTime: Int64;
begin
{建立 WaitableTimer 对象并返回句柄}
hWaitableTimer := CreateWaitableTimer(nil, True, nil); {中间的 True 表示可驱动多个线程}
DueTime := 0; {这将是 SetWaitableTimer 的第二个参数; 因为是 var 参数, 不能直接给常量}
SetWaitableTimer(hWaitableTimer, {WaitableTimer 对象的句柄}
DueTime, {起始时间, 这里给的是 0}
0, {间隔时间, 这里给的也是 0}
nil, {暂不用回调函数}
nil, {当然也不需要给回调函数参数了}
False {此值若是 True, 即使系统在屏保或待机状态, 时间一到线程和系统将都被唤醒!}
);
end;
{再说明:
起始时间(第二个参数)有三种赋值方法:
1、> 0 时是绝对时间, 是一个 TFileTime 格式的时间(具体赋值方法后面详解);
2、< 0 时是相对时间, 相对是相对于当前, 譬如 -50000000 表示 5 秒钟后执行(单位是0.1毫秒, 后面详述);
3、= 0 时, 立即执行, 不再等待; 上面的举例和下面第一个例子我们先用 0.
间隔时间(第三个参数)有两种情况:
1、譬如 5000 表示每隔 5 秒钟执行一次, 其单位是毫秒; 本页第二个例子使用了 500(半秒);
2、如果赋值为 0, 表示根据起始时间只执行一次, 不再重复执行.
回调函数及其参数(第四、五个参数), 这会牵扯出一个更复杂的话题(APC), 暂时不用它, 后面再说.
最后一个参数上面已经说清楚了, 我也测试了一下(分别在屏保和待机状态下), 很有效!
}
end;
{再说明:
起始时间(第二个参数)有三种赋值方法:
1、> 0 时是绝对时间, 是一个 TFileTime 格式的时间(具体赋值方法后面详解);
2、< 0 时是相对时间, 相对是相对于当前, 譬如 -50000000 表示 5 秒钟后执行(单位是0.1毫秒, 后面详述);
3、= 0 时, 立即执行, 不再等待; 上面的举例和下面第一个例子我们先用 0.
间隔时间(第三个参数)有两种情况:
1、譬如 5000 表示每隔 5 秒钟执行一次, 其单位是毫秒; 本页第二个例子使用了 500(半秒);
2、如果赋值为 0, 表示根据起始时间只执行一次, 不再重复执行.
回调函数及其参数(第四、五个参数), 这会牵扯出一个更复杂的话题(APC), 暂时不用它, 后面再说.
最后一个参数上面已经说清楚了, 我也测试了一下(分别在屏保和待机状态下), 很有效!
}
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论