DECLARE Sleep IN Win32API INTEGER
SLEEP(0)
尽管可以在单处理器计算机上使用多线程,但请注意多线程可能会导致意料不到的结果。例如,在单处理器计算机上,多线程仅在长短任务混杂的情况下可以显著地提高性能。多线程方法程序调用也可能会使速度降低。
例如,假设同时调用两个方法程序:A 和 B。在单线程组件,请求是串行,除非 A 结束否则不会开始 B。在多线程情况下,处理器将并发处理两个活动的线程。
不仅平均完成时间增加了很多,而且处理器时间花费在进程之间的切换上。问题在于方法程序 A 和 B 花费大致相同的时间量。
例如,如果 B 仅请求了三个时间片以完成任务,在方法程序 B 的响应时间内系统的用户将感觉到速度有很大的提高,仅在请求执行方法程序 A 的时间中有一些降低。
多线程显示其最大优越性是在以下情况:大多数线程花费了大量阻塞时间,例如,等待文件输入/输出,这样一来,在任意给定的时间上其他线程可以执行代码。
如果要考虑在单处理器上运行应用程序,并且线程阻塞是最小限度,可以考虑使用 Vfp6r.dll 运行时刻库。在多处理器上并且在大多数其他应用程序中,可以考虑为 .dll 服务程序使用 Vfp6t.dll。
重入
在套件模型中,重入引用以下的事件系列:
执行套件的线程重入了一个对象的代码,原因是触发了某个属性和方法程序。
当线程在属性或方法程序中时,其他线程触发了对象的属性或方法程序,Automation 连续发出请求,也就是说,Automation 对请求进行排队,直到拥有对象的套件的线程完成了其并发执行的成员。
在线程到达成员的结尾之前,它执行让出处理器控制的代码。
Automation 通知线程开始执行连续的请求,这样线程就重新重入了对象的代码。
新的请求可能是针对线程正在执行的成员的(在线程再次重入成员的情况下),也可能是针对其他程序的。如果第二个成员没有退出,它将在第一个成员之前完成处理。如果它更改了第一个成员正在使用的模块级数据,则结果可能出现问题。
通过对每个套件属性和方法程序的连续调用,Automation 保护您的代码以防止重新重入,除非您的代码让出了处理器的控制。以下是在代码中让出处理器控制的方法:
调用 DoEvents。
在其他线程或其他进程上触发属性或方法程序。如果将 Application.AutoYield 属性设置为假 (.F.),则将在代码执行之间挂起间歇事件的处理过程。
从方法程序中触发交叉线程或交叉进程方法程序。
除非已经小心地书写了所有对象的代码,使代码在同时执行两个成员的情况下不会有问题,否则就应该插入让出处理器控制的代码。
新的 Vfp6t.dll 运行时刻库将保护对象以避免访问其他应用程序的数据。它同时包含了声明的和内部的环境全局资源。某些资源代表了潜在的冲突问题,如下所示。
文件输入/输出代表的资源冲突可以很容易地通过代码解决,因为文件管理是通过操作系统来处理的。当使用文件时,您的服务程序可以打开(并锁定)文件,以便使其他对象知道该文件正在使用。撰写正确的服务程序可以处理这种情况,方法是一直等待直至文件重新可用为止,或者通过其他较容易接受的方式处理错误。文件也可以“共享”地打开,在这种情况下,服务程序应该意识到其他对象存在更改值的可能性。
对于 INI 文件,一个常见的情况就是不同的对象可以读或写文件中的值。读出并且随后将值写入 INI 文件的进程需要两步。因此,就有可能发生这样的情况:由一个客户应用程序读出的值,如果其他客户应用程序在其更改之前更改了该值,则该值就不一定是该客户应用程序后来覆盖的同一个值,因此就需要进行冲突解决。
与 INI 文件相同,“注册表”中保存的设置也可以由多个客户应用程序访问。您的应用程序应该使用公用的 Windows API 例程来访问“注册表”(例如,REGISTRY.VCX 中的 FoxPro“基本”类)。同样,您的服务程序设计应该反映在读取键值时刻和写入键值时刻之间对“注册表”键值可能的更改。Windows API 例程工作时可以不必进行冲突解决。
“数据”是一种需要灵活处理的资源。庆幸的是,大多数在运行时刻库中可用的 Visual FoxPro 语言提供了处理资源冲突问题所需要的全部信息和功能。有关处理共享数据的详细内容,请参阅“帮助”中的“编写共享访问的程序”。