大家好,欢迎来到IT知识分享网。
一、初识
1.单元文件
在 Delphi 中,单元(Unit)是组织代码的基本结构。每个单元通常包括接口部分、实现部分以及可选的初始化和结束部分。
一个 Delphi 单元文件(.pas
文件)通常分为四个主要部分:
interface
:接口部分,声明对外可见的常量、类型、变量和过程/函数。implementation
:实现部分,定义接口部分声明的过程/函数的具体实现。initialization
:初始化部分,包含单元初始化时要执行的代码(可选)。finalization
:结束部分,包含单元结束时要执行的代码(可选)。
1.1 interface部分
用途:
interface
部分声明单元对外公开的内容,包括常量、类型、变量、过程和函数等。这些声明可以被其他引用此单元的单元或程序使用。
组成:
uses
:声明此单元依赖的其他单元。任何放在uses
子句中的单元都将被引入并可用于当前单元的接口部分。- 声明的常量、类型、变量、过程和函数等。
1.2 implementation部分
用途:implementation
部分包含了 interface
部分中声明的过程和函数的实现细节。这部分的内容对于使用该单元的其他单元或程序是不可见的。
组成:
uses
:如果需要在实现部分引用其他单元,这里可以再次使用uses
子句声明。这部分的uses
子句仅对实现部分有效。- 具体的过程和函数的实现代码。
1.3 initialization部分
用途:initialization
部分用于定义单元初始化时要执行的代码。当单元被加载时,这部分代码会自动执行。
注意:在 initialization
部分中,你可以执行一些初始化操作,如变量的初始赋值、对象的创建等。
1.4 finalization部分
用途:finalization
部分定义了在单元卸载时要执行的代码,通常用于清理资源、释放内存等操作。
注意:这部分的代码在程序退出时自动执行。
二、基本数据类型
- 整型:
- 实数:
- 字符类型
- 布尔类型
1.定义一个变量
1.1 变量的声明
var 变量名:数据类型;
1.2 变量的赋值
变量名:=变量的值;
1.3 变量的定义
2.定义一个常量
- 不指定常量类型
- 指定常量类型
3.定义一个枚举类型
4.定义一个子界
“子界”(Subrange)是 Pascal 语言中的一个概念,它允许程序员定义一个变量的取值范围,以确保该变量只接受特定范围内的值。这在编写安全和高效的代码时非常有用,因为它通过限制值的范围来减少错误的发生。子界类型可以用于整数、字符和枚举类型等。
type 子界名 = 下界..上界;
5.定义一个集合
在 Pascal 语言中,集合(Set)是一种非常有用的数据结构,它可以存储一组同一类型的元素,并且提供了方便的操作来检查元素是否属于集合、添加或删除元素、以及进行集合的并集、交集和差集操作。
语法:
type SetName = set of ElementType;
5.1 集合的赋值
5.2 集合的并交差运算
5.3 集合的关系运算
6.定义一个记录类型
在 Pascal 中,记录类型(Record)是一种非常有用的数据结构,用于将不同类型的多个数据元素组合在一起,形成一个逻辑上的整体。这种类型特别适合表示复杂的数据结构,比如表示学生信息、员工信息、点的坐标等。
- 实现一个学生信息管理系统
7.定义一个指针类型
指针是一个变量,它存储另一个变量的内存地址。通过指针,你可以访问、修改该地址中的数据。
var P: ^Integer; // 声明一个指向 Integer 类型的指针 X: Integer; begin X := 42; P := @X; // P 指向变量 X 的地址 Writeln(P^); // 输出 42,即通过指针访问 X 的值 end;
在这个例子中,P
是一个指向 Integer
类型的指针。@X
取得变量 X
的内存地址,然后将其赋值给 P
。P^
表示指针 P
指向的地址所存储的值,即 X
的值。
指针在动态内存分配中非常重要。Delphi 提供了 New
和 Dispose
过程来分配和释放内存。
New
:为指针分配内存。Dispose
:释放指针所指向的内存。
var P: ^Integer; begin New(P); // 分配内存 P^ := 100; // 给指针指向的内存赋值 Writeln(P^); // 输出 100 Dispose(P); // 释放内存 end;
- 无类型指针
三、运算符
- 算术运算符: + – / * div(整除) mod(求模、求余数)
- 关系运算符
四、程序流程控制
1.普通语句
1.1 赋值语句
1.2 复合语句
1.3 With语句
with
语句是 Delphi 中的一种语法结构,用来简化对对象或记录的多个属性或字段的访问。通过使用 with
语句,你可以避免多次重复地写对象或记录的名称,从而使代码更简洁、易读。
当你使用 with
语句时,Delphi 会在 with
块内部自动处理对象或记录的名称。在 with
块中,你可以直接访问该对象或记录的属性或字段,而不必重复写对象或记录的名称。
2.控制语句
2.1 选择语句
2.2 循环语句
2.2.1 for循环
for
循环是一种计数循环,用于在已知重复次数的情况下执行代码块。for
循环有两种形式:for...to...do
和 for...downto...do
。
2.2.2 while循环
while
循环是一种前测试条件的循环,它在每次迭代前首先检查条件是否为真。如果条件为真,则执行循环体;如果为假,则退出循环。适用于循环次数不确定,但需满足某个条件时。
2.2.3 repeat循环
repeat...until
循环是一种后测试条件的循环,它先执行一次循环体,然后检查条件。如果条件为假,循环继续执行;如果条件为真,循环结束。适用于至少需要执行一次循环体的情况。
3. 异常
五、数组
数组(array)是 Pascal 中一种非常重要的数据结构,用于存储具有相同类型的一组元素。数组允许通过索引访问元素,并且索引通常是整数类型。数组的大小可以在编译时确定,或者在运行时通过动态分配确定。
1.静态数组
静态数组在编译时定义大小,并且其大小在程序执行期间不可更改。
语法:
type ArrayName = array[IndexType] of ElementType;
IndexType
是用于索引数组的类型,通常是整数类型或枚举类型。ElementType
是数组中元素的类型。
- 遍历:
2.动态数组
动态数组是在运行时分配大小的数组,可以在程序执行过程中调整其大小。动态数组使用 SetLength
函数来分配和调整大小。
- 其他初始化方法
3.多维数组
多维数组是 Pascal 语言中的一种数据结构,它允许你在单个变量中存储多个维度的相同类型的元素。多维数组特别适用于表示矩阵、表格或其他复杂的数据结构。
六、例程
例程通常包括两种主要形式:过程(Procedure)和函数(Function)。
过程(Procedure)
- 定义:过程是一个可以执行特定任务的代码块,但不返回任何值。
- 用途:过程通常用于执行某些动作,比如显示信息、处理数据、执行计算或调用其他例程。
函数(Function)
- 定义:函数是一个执行特定任务的代码块,它除了执行动作之外,还会返回一个值。
- 用途:函数通常用于计算结果或获取特定值。
1. 参数传递
- 按值传递(By Value)
- 概念:按值传递是将参数的值复制一份传递给过程或函数。在过程或函数内部对参数的修改不会影响到外部的变量,因为传递的是参数的副本。
- 默认行为:在 Delphi 中,所有不加修饰符的参数默认是按值传递的。
- 按引用传递(By Reference)
- 概念:按引用传递是将参数的内存地址传递给过程或函数,因此在过程或函数内部对参数的修改会直接影响到外部的变量。
- 在 Delphi 中,可以使用
var
关键字来指定按引用传递。
- 常量传递(By Const)
- 常量传递是将参数按值传递,但参数在过程或函数内部是只读的,不能修改其值。常量传递的效率通常比按值传递高,尤其是在传递结构较大且不需要修改的参数时。
- 在 Delphi 中,使用
const
关键字指定常量传递。
- out 参数传递的特点
- 和
var
参数一样,out
参数也是按引用传递的,这意味着传递的是变量的地址而不是值。因此,在过程或函数内部对out
参数的任何修改都会影响调用者提供的变量。 - 在传递给过程或函数之前,
out
参数不需要被初始化。这与var
参数不同,var
参数通常要求在调用前进行初始化。 - 当一个变量作为
out
参数传递时,Delphi 会自动将其清零或重置为默认值(对于对象类型,设置为nil
)。这意味着你不需要显式地初始化这个变量,也不需要担心之前的值。 out
参数设计的主要目的是将值从过程或函数返回给调用者。通常情况下,out
参数用于那些只需要从过程或函数获取值的场景,而不需要使用过程或函数传入的初始值。
- 和
2. 变量作用域
2.1 公有变量(Public Variable)
- 声明部分:
interface
- 作用范围:整个
pas
文件,以及其他引用了该pas
文件的单元。
公有变量是在 unit
的 interface
部分声明的变量。由于 interface
部分对其他单元是公开的,这些变量可以在当前单元及任何引用该单元的其他单元中使用。
公有变量通常用于在多个单元之间共享数据,或者在需要跨单元访问某些数据时使用。
unit Unit1; interface var SharedVariable: Integer; // 公有变量,可以在其他单元中访问 implementation end.
2.2 私有变量(Private Variable)
- 声明部分:
implementation
- 作用范围:仅限于当前
pas
文件。
说明:
- 私有变量是在
unit
的implementation
部分声明的变量。由于implementation
部分仅对当前单元可见,其他单元无法访问这些变量。 - 私有变量用于在单元内部保存状态或数据,不希望这些数据被其他单元访问。
unit Unit1; interface implementation var InternalVariable: Integer; // 私有变量,仅限于当前单元内访问 end.
2.3局部变量(Local Variable)
- 声明部分:过程/函数内部
- 作用范围:仅限于声明它的过程或函数内部。
说明:
- 局部变量是在过程或函数内部声明的变量。这些变量的作用范围仅限于声明它们的过程或函数内部,一旦过程或函数执行结束,这些变量就会被销毁。
- 局部变量用于存储在过程或函数执行期间所需的临时数据。
procedure MyProcedure; var LocalVariable: Integer; // 局部变量,仅在该过程内有效 begin LocalVariable := 10; end;
2.4全局变量(Global Variable)
- 声明部分:过程/函数外
- 作用范围:整个程序。
说明:
- 全局变量是在单元的
interface
或implementation
部分声明的变量,但它们在整个程序中都可以访问。通常,Delphi 的全局变量指的是在interface
部分声明的变量,因为它们在多个单元中可见。 - 全局变量用于在整个程序的多个部分之间共享数据。需要注意的是,全局变量的使用应当谨慎,以避免数据的意外修改或程序的可维护性下降。
var GlobalVariable: Integer; // 全局变量,整个程序中都可以访问 procedure MyProcedure; begin GlobalVariable := 100; end;
七、类与对象
类是对象的蓝图,它定义了对象的属性(字段、变量)和行为(方法、函数、过程)。在 Delphi 中,类使用 class
关键字定义。
1.类的成员
字段(Field)
字段是类中的变量,用来存储对象的状态。字段可以是私有的、受保护的或公有的。
私有字段:使用 private
关键字定义,只有类内部可以访问。
受保护的字段:使用 protected
关键字定义,类和其子类可以访问。
公有字段:使用 public
关键字定义,任何地方都可以访问。
type TMyClass = class private FPrivateField: Integer; protected FProtectedField: Integer; public FPublicField: Integer; end;
方法(Method)
方法是类中的函数或过程,用于定义对象的行为。方法可以是私有的、受保护的或公有的,与字段的访问级别类似。
type TMyClass = class public procedure ShowMessage; // 公有方法 end; procedure TMyClass.ShowMessage; begin Writeln('Hello, World!'); end;
2.构造函数和析构函数
- 自定义构造函数
3.属性
属性是字段的抽象化,允许你使用类似于字段的语法访问类的私有数据,同时可以通过 getter
和 setter
方法控制访问。
当你使用 Calc.Symbol
时,实际上是调用了 GetSymbol
和 SetSymbol
方法,而不是直接访问 FSymbol
。
Calc.Symbol := '+';
等同于 Calc.SetSymbol('+');
,这会调用 SetSymbol
方法,将 +
赋值给 FSymbol
。
4.创建和销毁对象
在 Delphi 中,创建对象通常使用 Create
方法,而销毁对象则使用 Free
方法。
var MyObject: TMyClass; begin MyObject := TMyClass.Create; // 创建对象 try // 使用 MyObject finally MyObject.Free; // 销毁对象 end; end;
Free
方法:Free
方法检查对象是否为 nil
,如果不是,则调用 Destroy
方法,并将对象指针设置为 nil
。
5.类的方法
5.1静态方法
关键字:无
默认情况下,如果方法没有使用 virtual
、dynamic
或 override
声明,则它是一个静态方法。
调用静态方法时,编译器会直接将调用目标方法的地址嵌入到调用代码中,因此调用速度是最快的。
5.2虚拟方法
关键字:virtual
使用 virtual
关键字声明的方法是虚拟方法。虚拟方法表(VMT)用于支持多态性。
当调用虚拟方法时,编译器会通过 VMT 查找实际的方法地址,这允许子类重写该方法,并且调用总是指向最合适的子类实现。
虚拟方法的调用略慢于静态方法,因为它涉及一次额外的内存查找。
5.3动态方法
关键字:dynamic
dynamic
方法的作用类似于虚拟方法,但它使用动态方法表(DMT)而不是虚拟方法表(VMT)。
dynamic
方法的调用机制相对来说比虚拟方法更节省内存,因为 DMT 是一种稀疏数据结构,在子类不重写该方法时不会占用内存。
由于 DMT 的查找比 VMT 更复杂,所以 dynamic
方法的调用速度比 virtual
方法稍慢。
5.4类方法
关键字:class
在 Delphi 中,类方法(class methods) 具有类似于C++静态方法的行为。可以通过类名调用的方法,可以访问类的静态成员和类方法。
5.5抽象方法
关键字:abstract
在 Delphi 中,抽象方法是用来定义在基类中的方法,但基类不提供该方法的实现,而是留给派生类去实现。这种方法定义了一个接口,指定了派生类应该实现哪些方法。
在 Delphi 中,抽象方法使用 abstract
关键字。要定义一个抽象方法,你首先将方法声明为 virtual
或 dynamic
,然后在方法声明的末尾加上 abstract
关键字。抽象方法通常不提供具体的实现,只是在声明中描述它的接口。
一个包含抽象方法的类通常被称为抽象类。抽象类不能被实例化,因为它无法提供对抽象方法的具体实现。只有在派生类中实现了所有抽象方法后,才能实例化该派生类。
5.6消息方法
使用 message
关键字的方法用于处理 Windows 消息(如窗口事件)。这类方法使用消息映射机制来处理方法调用。
静态方法(static
):不能访问类的实例成员,只能访问静态成员或全局成员。
class procedure TMyClass.StaticMethod; static; begin Writeln('Static method called'); end;
类方法(class
):可以通过类名调用的方法,可以访问类的静态成员和类方法。
class procedure TMyClass.ClassMethod; begin Writeln('Class method called'); end;
6.继承
6.1构造
在 Delphi 中,当继承了一个类并实现子类的构造函数时,需要显式调用父类的构造函数。
如果不这样做,Delphi 不会自动调用父类的构造函数,这与 C++的行为有所不同。
父类:
子类:
- 显式使用
inherited
关键字来调用父类构造函数。
增加一个构造函数用来初始化继承的父类属性。
- 重写父类方法
6.2访问权限
- 父类public、protected,子类正常访问。
- 父类private,子类无法访问。
6.3多态
派生类必须加override指明该方法是重写父类的动态方法。
- 向上转型
在 Delphi 中,as
和 is
是两个用于类型转换和类型检查的关键字。它们在处理对象和接口类型时非常有用,尤其是在涉及多态性和接口的场景中。
is
关键字
is
用于检查一个对象实例是否属于某个特定的类或其子类。它返回一个布尔值 (True
或 False
),表示对象是否是指定类型的实例或其派生类型的实例。
as
关键字
as
用于将对象转换为特定的类或接口类型。它尝试将对象转换为指定类型,并返回该类型的实例。如果转换失败(即对象不是指定类型的实例),则会引发 EInvalidCast
异常。
7.类的事件
事件是一种非常灵活的机制,可以允许类在发生某个操作时通知其他对象或代码执行。事件背后的机制是方法指针,你可以将一个方法赋值给事件处理程序,并在特定时机调用该事件。
定义类的事件
在一个类中定义事件,通常步骤如下:
- 声明事件类型。
- 声明一个事件变量。
- 在类的适当时机调用该事件。
八、接口
在 Delphi 中,接口(Interface)是用来定义一个契约或协议的,它描述了一个类应该具备的功能,而不涉及具体的实现。接口与类不同,它不包含任何数据成员或已实现的方法,而是只包含方法的声明。这些方法必须在实现接口的类中提供具体实现。
Delphi 中接口的特点
- 纯虚类:接口类似于一个纯虚类。它不能直接实例化,而是通过实现接口的类来实现接口中的方法。
- 引用计数:Delphi 中的接口具有自动引用计数的特点,这意味着接口会自动管理内存,减少内存泄漏的风险。当接口的引用计数达到零时,系统会自动释放内存。
- 多重继承:Delphi 中的类不支持多重继承,但接口支持多重实现。这意味着一个类可以实现多个接口,从而实现不同的功能。
- 接口与类的关系:在 Delphi 中,接口与类的关系类似于一种契约。实现某个接口的类必须提供接口中声明的所有方法的实现。
- GUID:每个接口都可以(但不是必须)与一个全球唯一标识符(GUID)关联。GUID 用于在运行时标识接口,特别是在 COM(组件对象模型)编程中。
如果不提供接口的方法的具体实现就会编译出错。
- 一个类实现多个接口
什么时候用接口?
是否使用接口,通常取决于以下几个因素:
1. 需要定义一个契约或协议时
接口可以定义一个契约或协议,规定实现该接口的类必须提供哪些方法。这在以下情况中特别有用:
- 多态性:当你希望对一组不同的类进行相同的操作时,可以使用接口。例如,你可能有多个不同的类
(如
TDog
、TCat
、TBird
),但它们都实现了IAnimal
接口,这样你可以在不关心具体类的情况下调用
Speak
方法。 - 插件架构:在构建可扩展的应用程序时,接口可以定义插件的标准。插件只需要实现接口,即可被主程序调用。
2. 需要实现松耦合时
接口有助于降低类之间的耦合度。通过接口,类只需知道接口的定义,而不需要了解具体的实现。这样,当实现发生变化时,对接口的依赖不会受到影响。
- 依赖倒置原则:接口允许你将高层模块与低层模块解耦合,高层模块依赖于抽象(接口),而不是具
体实现。这是依赖倒置原则(Dependency Inversion Principle)的核心思想。
3. 支持多重继承时
Delphi 不支持类的多重继承,但一个类可以实现多个接口。这允许你在同一个类中实现多个不同的契约,这在需要类具有多种不同的行为时非常有用。
- 多角色对象:一个类可能需要在不同的上下文中扮演不同的角色。例如,一个对象可能既是一个
IUser
,也是一个IManager
。通过接口可以轻松实现这种情况。
4. 替换复杂的继承结构时
当你发现类的继承结构变得过于复杂时,使用接口可能是一个更好的选择。接口可以帮助你摆脱深度继承树,转而使用组合(Composition)来代替继承。
- 避免继承的复杂性:继承带来的复杂性可能会导致代码难以理解和维护。接口通过将行为分离为不同的
契约,可以简化类的设计。
5. 需要不同类的对象有相似的行为时
在设计时,可能会有多个不同的类,它们没有共同的父类,但是它们的某些行为是相似的。此时,可以通过接口来统一这些行为,使得它们可以被相同的代码处理。
- 统一操作:例如,
TPrinter
和TScreen
类可能都需要实现IDrawable
接口,使得它们可以被同一个绘图操作所处理。
6. 需要第三方或插件扩展时
接口在设计第三方扩展或插件系统时非常重要。通过接口,主应用程序可以定义插件需要实现的功能,而插件开发者只需实现这些接口即可。
- 扩展性:例如,设计一个支持不同支付方式的电商平台,您可以定义一个
IPaymentProcessor
接口,支持的支付方式只需要实现这个接口即可被主程序调用。
7. 接口与抽象类的对比
在某些情况下,您可能会考虑是使用接口还是抽象类。一般来说:
- 接口:用于定义行为的契约,没有任何实现细节。
- 抽象类:用于在同一个类层次结构中共享代码,并且可以包含部分实现。
九、泛型容器
十、线程
假如我们有一段执行运算的代码,同时想要动态地将每次运算结果更新到UI中,如果没有使用多线程,就会出现界面卡死的情况,直到运算执行完毕,UI直接显示最终结果。
因此我们创建一个线程类,在构造函数中传入TLabel控件。
1.如何暂停和继续执行线程
关于Tevent的构造函数。
constructor TEvent.Create( EventAttributes: PSecurityAttributes; ManualReset,InitialState: Boolean; const Name: string; UseCOMWait: Boolean );
参数详解:
- AEventAttributes (nil)
- 类型:
PSecurityAttributes
- 说明:这是一个指向
PSecurityAttributes
的指针,用于定义事件的安全属性。在一般情况下,这个参数可以设置为nil
,表示使用默认的安全属性。
- 类型:
- ManualReset (True)
- 类型:
Boolean
- 说明:指定事件对象的重置模式。
True
表示手动重置事件。当事件被设为有信号状态后,必须手动调用ResetEvent
方法将其重置为无信号状态。此模式适用于当一个或多个线程需要等待某一条件时使用。False
表示自动重置事件。当事件被设为有信号状态后,系统会自动将其重置为无信号状态,且仅会释放一个等待线程。适用于只需要唤醒一个等待线程的场景。
- 类型:
- InitialState (False)
- 类型:
Boolean
- 说明:设置事件的初始状态。
True
表示事件初始为有信号状态。False
表示事件初始为无信号状态。此状态下,调用WaitFor
方法的线程将被阻塞,直到事件状态被设置为有信号。
- 类型:
- Name (‘’)
- 类型:
string
- 说明:指定事件对象的名称。通过名称,可以在不同进程间共享事件对象。
- 如果设置为
''
(空字符串),表示事件对象不具备名称,因此它只能在当前进程中使用。 - 可以指定一个名称,这样在进程间通信中,可以使用相同的名称来访问这个事件对象。
- 如果设置为
- 类型:
2.终止线程
使用 Terminate
方法来控制线程终止是 Delphi 的标准做法
不要在设置了 FreeOnTerminate := True
的情况下手动调用 Free
:
- 如果你将
FreeOnTerminate
设置为True
,就不需要手动释放线程对象,因为它会在终止时自动释放。
3.线程同步
首先这里创建了一个线程类,进行卖票,从第一张卖到第十张。
只有一个线程执行的结果如下:
如果有多个线程执行,结果就会混乱并且没有唯一性:
此时就需要使用线程同步的方法,避免出现多线程争用同一资源导致的错误。
3.1 Synchronize
Synchronize
是 Delphi TThread
类提供的一个方法,用于在主线程(UI 线程)中执行某些代码。由于 VCL(Visual Component Library)控件并不是线程安全的,所以我们不能直接在工作线程中操作它们,否则可能导致不可预期的行为或崩溃。Synchronize
解决了这个问题,确保在主线程中执行对 VCL 控件的操作。
在 Execute
方法中使用了 Synchronize
,这会导致 DoWork
方法在主线程中执行。由于 Synchronize
会阻塞工作线程,直到主线程执行完该方法,所以即使创建了多个线程,它们也不会同时执行 DoWork
。当然这种方法不太适用于临界区的情况,一般是用来更新UI的。
3.2 TCriticalSection
用途:TCriticalSection
是一种轻量级的同步机制,用于保护代码块或数据结构,使得在同一时刻只有一个线程可以访问它。适用于同一进程中的线程同步。
原理:TCriticalSection
使用进入/离开(Enter/Leave)方法保护共享资源。一个线程在进入临界区时会锁定它,其他试图进入的线程将被阻塞,直到临界区被释放。
注意事项:
如果还想要在 mmo1
中显示信息,因为 DoWork
现在是在工作线程中执行的,应该将 Form1.mmo1.Lines.Add(...)
这部分代码放在 Synchronize
中,这样可以保证对 VCL 控件的操作是安全的。
3.3 TMutex
用途:TMutex
用于多线程和多进程同步。它可以在不同的进程间共享,以确保只有一个线程或进程可以访问共享资源。
原理:TMutex
基于操作系统提供的互斥量实现。线程通过请求和释放互斥量来控制对资源的访问。
优点:可以在不同进程之间同步。
缺点:比 TCriticalSection
开销更大,使用系统资源。
constructor TMutex.Create( MutexAttributes: PSecurityAttributes; InitialOwner: Boolean; const Name: string; UseCOMWait: Boolean = False );
MutexAttributes
: 一个指向 SECURITY_ATTRIBUTES
结构的指针,定义了互斥对象的安全属性。在多数情况下,你可以传入 nil
,表示使用默认的安全属性。
InitialOwner
: 一个布尔值,如果为 True
,则调用线程在创建互斥对象时立即拥有它。如果为 False
,则互斥对象创建后处于未拥有状态。
Name
: 互斥对象的名称,可以用来在不同进程之间共享。如果传入空字符串,则创建一个匿名互斥对象。
UseCOMWait
: 同上,指定是否允许在等待期间处理消息和 COM 调用。
3.4 TEvent
1.如何暂停和继续执行线程 这里说过
3.5 TMonitor
用途:TMonitor
是 Delphi 提供的高级同步机制,用于简化线程同步。它为对象提供了进入/离开临界区的功能,并且支持条件变量的等待和通知。
原理:TMonitor
内部维护了一个临界区(类似于 TCriticalSection
)和条件变量(类似于 TEvent
),允许线程等待某个条件,并在满足条件时通知等待的线程。
TMonitor
的主要方法
- Enter / Exit:
Enter
方法用于获取锁,Exit
方法用于释放锁。这两个方法通常成对使用,确保锁在获得后会被释放。 - TryEnter: 尝试获取锁,如果锁被其他线程持有,
TryEnter
会立即返回False
,否则返回True
表示成功获取锁。 - Wait: 在当前线程中等待,直到收到来自其他线程的通知。
Wait
会释放当前锁定并进入等待状态,直到Signal
或Pulse
方法被调用。 - Pulse: 唤醒等待线程中的一个。
- PulseAll: 唤醒所有等待线程。
4.生产者消费者问题
十一、DLL
1.动态调用
2.静态调用
3.DLL的初始化和退出
Delphi 可以通过 DllProc
来处理加载和卸载事件。通过将 DllProc
设置为回调函数,处理 DLL 的加载(DLL_PROCESS_ATTACH
)和卸载(DLL_PROCESS_DETACH
)事件。
免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://haidsoft.com/139796.html