线程

简单来说,程序可以看作是开发者为计算机生成的一系列语句。计算机中语句的主要执行者是中央处理器。现代计算机通常配备多核处理器,相当于拥有多个独立处理器。然而,用户可能想要并行运行的程序数量几乎是无限的。因此,程序的数量始终比可用内核/处理器数量多很多倍。为此,每个内核实际上会将其工作时间分配给多个不同程序:先分配 1 毫秒执行一个程序的语句,再分配 1 毫秒执行另一个程序的语句,接着是第三个程序,依此类推,循环往复。由于这种切换速度非常快,用户不会察觉到这一点,好像所有程序都是同时并行执行的。

为了让处理器能够暂停一个程序的语句执行,并在之后(当它悄悄切换到其他“并行”程序的语句后)从之前的位置恢复执行,它必须能够以某种方式保存和恢复每个程序的中间状态:包括当前语句、变量、可能已打开的文件、网络连接等。程序正常运行所需的全部资源和数据,及其在语句序列中的当前位置,统称为程序的执行上下文。实际上,操作系统的设计目的是根据用户(或其他程序)的请求为每个程序创建这样的上下文。每一个这样的活动上下文都被称为线程。许多程序自身需要多个线程,因为其功能涉及并行维持多个活动。MetaTrader 5 同样需要多个线程来加载多个交易品种的报价、绘制图表以及响应用户操作。此外,系统也会向 MQL 程序分配单独的线程。

MQL 程序执行环境为每个程序分配的线程数不超过一个。每个 EA 交易、脚本和服务都严格获得一个线程。至于指标,同一金融工具上运行的所有指标会分配一个线程。而且,同一个线程负责显示相应交易品种的图表,所以不建议让它执行密集型计算。否则,用户界面将变得无响应:用户操作的处理会被延迟,或者窗口甚至会变得无响应。所有其他类型的 MQL 程序的线程都不与界面绑定,因此可以让处理器执行任何复杂的任务。

线程的一个重要特性源自其定义和用途:它仅支持按顺序依次执行语句的语句。在一个线程中,一次只执行一条语句。如果在程序中编写了一个无限循环,线程将卡在这条指令上,并且永远不会执行其下面的指令。冗长的计算也可能产生类似无限循环的效果:它们会占用处理器,阻碍执行用户可能期望的其他操作。因此,指标中保持高效计算对图形界面的流畅运行至关重要。

然而,对于其他类型的 MQL 程序,应重视线程安排。在接下来的章节中,我们将详细了解作为 MQL 程序入口点的特殊事件处理函数。单线程模型意味着在处理一个事件的过程中,程序对可能同时发生的其他事件是无响应的。因此,终端会为每个程序维护一个事件队列。在下一章节中,我们会更详细地探讨这一点。

为了在实践中体验单线程的效果,我们将 指标的优势与局限 (IndBarIndex.mq5) 章节中查看一个简单的示例。我们选择指标作为示例,是因为它们不仅针对每个交易品种共享一个线程,还直接在图表上显示结果,这使得潜在的问题能够最直观地显现出来。