吉星星 發表於 2024-6-11 00:25:00

mormot.core.threads.pas unit

<h1 id="mormotcorethreadspas-unit-中文翻译">mormot.core.threads.pas unit 中文翻译</h1>
<p><em>Purpose</em>: Framework Core Multi-Threading Support<br>
- this unit is a part of the Open Source Synopse mORMot framework 2, licensed under a MPL/GPL/LGPL three license - see LICENSE.md</p>
<p><em>目的</em>:框架核心多线程支持</p>
<ul>
<li>本单元是开源Synopse mORMot框架2的一部分,根据MPL/GPL/LGPL三重许可进行许可-参见LICENSE.md</li>
</ul>
<h2 id="11-units-used-in-the-mormotcorethreads-unit-在mormotcorethreads单元中使用的单元">1.1. Units used in the <em>mormot.core.threads</em> unit (在<em>mormot.core.threads</em>单元中使用的单元)</h2>
<table>
<thead>
<tr>
<th><strong>Unit Name</strong></th>
<th><strong>Description</strong></th>
<th></th>
</tr>
</thead>
<tbody>
<tr>
<td>mormot.core.base</td>
<td>Framework Core Shared Types and RTL-like Functions</td>
<td>框架核心共享类型和类似RTL的函数</td>
</tr>
<tr>
<td>mormot.core.buffers</td>
<td>Framework Core Low-Level Memory Buffer Process</td>
<td>框架核心低级内存缓冲区处理</td>
</tr>
<tr>
<td>mormot.core.data</td>
<td>Framework Core Low-Level Data Processing Functions</td>
<td>框架核心低级数据处理函数</td>
</tr>
<tr>
<td>mormot.core.json</td>
<td>Framework Core Low-Level JSON Processing</td>
<td>框架核心低级JSON处理</td>
</tr>
<tr>
<td>mormot.core.log</td>
<td>Framework Core Logging</td>
<td>框架核心日志记录</td>
</tr>
<tr>
<td>mormot.core.os</td>
<td>Framework Core Low-Level Wrappers to the Operating-System API</td>
<td>框架核心对操作系统API的低级包装器</td>
</tr>
<tr>
<td>mormot.core.perf</td>
<td>Framework Core Performance and Monitoring Classes</td>
<td>框架核心性能和监视类</td>
</tr>
<tr>
<td>mormot.core.rtti</td>
<td>Framework Core Low-Level Cross-Compiler RTTI Definitions</td>
<td>框架核心低级跨编译器RTTI定义</td>
</tr>
<tr>
<td>mormot.core.text</td>
<td>Framework Core Low-Level Text Processing</td>
<td>框架核心低级文本处理</td>
</tr>
<tr>
<td>mormot.core.unicode</td>
<td>Framework Core Low-Level Unicode UTF-8 UTF-16 Ansi Conversion</td>
<td>框架核心低级Unicode UTF-8 UTF-16 Ansi转换</td>
</tr>
<tr>
<td>mormot.core.variants</td>
<td>Framework Core Low-Level Variants / TDocVariant process</td>
<td>框架核心低级变量/TDocVariant处理</td>
</tr>
</tbody>
</table>
<h2 id="12-mormotcorethreads-class-hierarchy">1.2. <em>mormot.core.threads</em> class hierarchy</h2>
<p>TSynThread<br>
TSynThreadPoolWorkThread<br>
TNotifiedThreadTLoggedThread<br>
TLoggedWorkThreadTThreadAbstract<br>
TSynBackgroundThreadAbstract<br>
TSynBackgroundThreadProcess<br>
TSynBackgroundTimer<br>
TSynBackgroundThreadMethodAbstract<br>
TSynParallelProcessThread<br>
TSynBackgroundThreadProcedure<br>
TSynBackgroundThreadMethod<br>
TSynBackgroundThreadEventTThread<br>
TSynPersistentStoreTSynQueue<br>
TSynPersistentLockTSynParallelProcess<br>
TSynPersistent<br>
TBlockingProcessPool<br>
TBlockingProcess<br>
TBlockingProcessPoolItem<br>
TSynEventTObject<br>
TSynThreadPool<br>
TPendingTaskList<br>
TInterfacedObjectWithCustomCreate<br>
TLockedDocVariantIInterface<br>
ILockedDocVariant<br>
ESynException<br>
ESynThread</p>
<p><em>mormot.core.threads class hierarchy</em></p>
<p><img src="https://img2023.cnblogs.com/blog/370256/202406/370256-20240611001305957-1439315748.png" alt="image" loading="lazy"></p>
<h2 id="13-objects-implemented-in-the-mormotcorethreads-unit-mormotcorethreads-单元中实现的对象">1.3. Objects implemented in the <em>mormot.core.threads</em> unit (<em>mormot.core.threads</em> 单元中实现的对象)</h2>
<table>
<thead>
<tr>
<th><strong>Objects</strong></th>
<th><strong>Description</strong></th>
<th></th>
</tr>
</thead>
<tbody>
<tr>
<td>ESynThread</td>
<td>Exception class raised by this unit</td>
<td>由本单元引发的异常类</td>
</tr>
<tr>
<td>ILockedDocVariant</td>
<td>Ref-counted interface for thread-safe access to a TDocVariant document</td>
<td>用于线程安全访问TDocVariant文档的引用计数接口</td>
</tr>
<tr>
<td>TBlockingProcess</td>
<td>A semaphore used to wait for some process to be finished</td>
<td>一个计数信号量,用于等待某个进程完成</td>
</tr>
<tr>
<td>TBlockingProcessPool</td>
<td>Manage a pool of TBlockingProcessPoolItem instances</td>
<td>管理一组TBlockingProcessPoolItem实例</td>
</tr>
<tr>
<td>TBlockingProcessPoolItem</td>
<td>A semaphore used in the TBlockingProcessPool</td>
<td>在TBlockingProcessPool中使用的计数信号量</td>
</tr>
<tr>
<td>TLockedDocVariant</td>
<td>Allows thread-safe access to a TDocVariant document</td>
<td>允许线程安全地访问TDocVariant文档</td>
</tr>
<tr>
<td>TLoggedThread</td>
<td>Abstract class to implement a thread with logging notifications</td>
<td>实现带有日志通知的线程的抽象类</td>
</tr>
<tr>
<td>TLoggedWorkThread</td>
<td>A class able to run some process in a background thread</td>
<td>能够在后台线程中运行某些进程的类</td>
</tr>
<tr>
<td>TNotifiedThread</td>
<td>Abstract class to implement a thread with start/stop notifications</td>
<td>实现带有启动/停止通知的线程的抽象类</td>
</tr>
<tr>
<td>TPendingTaskList</td>
<td>Thread-safe list of tasks, stored as RawByteString, with a timestamp</td>
<td>线程安全的任务列表,以RawByteString形式存储,带有时间戳</td>
</tr>
<tr>
<td>TPendingTaskListItem</td>
<td>Internal item definition, used by TPendingTaskList storage</td>
<td>TPendingTaskList存储的内部项目定义</td>
</tr>
<tr>
<td>TSynBackgroundThreadAbstract</td>
<td>Abstract TThread with its own execution content</td>
<td>带有自己的执行内容的TThreadAbstract</td>
</tr>
<tr>
<td>TSynBackgroundThreadEvent</td>
<td>Allow background thread process of a method callback</td>
<td>允许在后台线程中处理方法回调</td>
</tr>
<tr>
<td>TSynBackgroundThreadMethod</td>
<td>Allow background thread process of a variable TThreadMethod callback</td>
<td>允许在后台线程中处理可变TThreadMethod回调</td>
</tr>
<tr>
<td>TSynBackgroundThreadMethodAbstract</td>
<td>Abstract TThread able to run a method in its own execution content</td>
<td>能够在自己的执行内容中运行方法的抽象TThread</td>
</tr>
<tr>
<td>TSynBackgroundThreadProcedure</td>
<td>Allow background thread process of a procedure callback</td>
<td>允许在后台线程中处理过程回调</td>
</tr>
<tr>
<td>TSynBackgroundThreadProcess</td>
<td>TThread able to run a method at a given periodic pace</td>
<td>能够在给定周期速率下运行方法的TThread</td>
</tr>
<tr>
<td>TSynBackgroundTimer</td>
<td>TThread able to run one or several tasks at a periodic pace in a background thread</td>
<td>能够在后台线程中以周期速率运行一个或多个任务的TThread</td>
</tr>
<tr>
<td>TSynBackgroundTimerTask</td>
<td>Used by TSynBackgroundTimer internal registration list</td>
<td>用于TSynBackgroundTimer内部注册列表</td>
</tr>
<tr>
<td>TSynParallelProcess</td>
<td>Allow parallel execution of an index-based process in a thread pool</td>
<td>允许在线程池中并行执行基于索引的进程</td>
</tr>
<tr>
<td>TSynParallelProcessThread</td>
<td>Thread executing process for TSynParallelProcess</td>
<td>为TSynParallelProcess执行进程的线程</td>
</tr>
<tr>
<td>TSynQueue</td>
<td>Thread-safe FIFO (First-In-First-Out) in-order queue of records</td>
<td>线程安全的FIFO(先入先出)有序记录队列</td>
</tr>
<tr>
<td>TSynThread</td>
<td>A simple TThread with a "Terminate" event run in the thread context</td>
<td>一个简单的TThread,带有在线程上下文中运行的"Terminate"事件</td>
</tr>
<tr>
<td>TSynThreadPool</td>
<td>A simple Thread Pool, used e.g. for fast handling HTTP/1.0 requests</td>
<td>一个简单的线程池,例如用于快速处理HTTP/1.0请求</td>
</tr>
<tr>
<td>TSynThreadPoolWorkThread</td>
<td>Defines the work threads used by TSynThreadPool</td>
<td>定义TSynThreadPool使用的工作线程</td>
</tr>
<tr>
<td>TThreadAbstract</td>
<td>Abstract parent of all TThread inherited classes</td>
<td>所有TThread继承类的抽象父类</td>
</tr>
</tbody>
</table>
<h3 id="131-esynthread-">1.3.1. ESynThread </h3>
<pre><code class="language-pascal">ESynThread = class(ESynException)
</code></pre>
<p><em>本单元引发的异常类</em></p>
<hr>
<h3 id="132-tsynqueue-">1.3.2. TSynQueue </h3>
<pre><code class="language-pascal">TSynQueue = class(TSynPersistentStore)
</code></pre>
<p>*线程安全的FIFO(先入先出)记录有序队列</p>
<ul>
<li>内部使用<code>TDynArray</code>存储,具有滑动算法,比FPC或Delphi的TQueue或简单的<code>TDynArray.Add</code>/Delete更高效</li>
<li>如果需要,支持<code>TSynPersistentStore</code>二进制持久化</li>
<li>该结构在设计上也是线程安全的*</li>
</ul>
<hr>
<pre><code class="language-pascal">constructor Create(aTypeInfo: PRttiInfo; const aName: RawUtf8 = ''); reintroduce; virtual;
</code></pre>
<p>*初始化队列存储</p>
<ul>
<li>aTypeInfo应是一个动态数组的TypeInfo() <code>RTTI</code>指针,它将在这个<code>TSynQueue</code>实例中存储值</li>
<li>可以为这个实例可选地分配一个名称*</li>
</ul>
<hr>
<pre><code class="language-pascal">destructor Destroy; override;
</code></pre>
<p>*销毁存储</p>
<ul>
<li>将释放所有内部存储的值,并调用<code>WaitPopFinalize</code>*</li>
</ul>
<hr>
<pre><code class="language-pascal">function Capacity: integer;
</code></pre>
<p>*返回当前在内存中预留的槽位数</p>
<ul>
<li>队列具有优化的自动调整大小算法,可以使用此方法返回其当前<code>capacity</code></li>
<li>此方法不是线程安全的,因此返回的值仅具有指示性*</li>
</ul>
<hr>
<pre><code class="language-pascal">function Count: integer;
</code></pre>
<p>*返回当前存储在此队列中的项数</p>
<ul>
<li>此方法不是线程安全的,因此返回的值要么具有指示性,要么应使用显式的安全锁定/解锁</li>
<li>如果要检查队列是否为空,请调用<code>Pending</code>*</li>
</ul>
<hr>
<pre><code class="language-pascal">function Peek(out aValue): boolean;
</code></pre>
<p>*从队列中按FIFO(先入先出)方式查找一个项</p>
<ul>
<li>如果aValue已被填充了一个<code>pending</code>项,而不从队列中删除它(如<code>Pop</code>方法所做的),则返回true</li>
<li>如果队列为空,则返回false</li>
<li>此方法是线程安全的,因为它将锁定实例*</li>
</ul>
<hr>

```pascal
function Pending: boolean;
```
<p>*如果队列中有一些当前<code>pending</code>的项,则返回true</p>
<ul>
<li>比检查<code>Count</code>=0更快,并且比<code>Pop</code>或<code>Peek</code>快得多</li>
<li>此方法不是线程安全的,因此返回的值仅具有指示性*</li>
</ul>
<hr>
<pre><code class="language-pascal">function Pop(out aValue): boolean;
</code></pre>
<p>*从队列中按FIFO(先入先出)方式提取一个项</p>
<ul>
<li>如果aValue已被填充了一个<code>pending</code>项,并且该项已从队列中删除(如果不想删除它,请使用<code>Peek</code>),则返回true</li>
<li>如果队列为空,则返回false</li>
<li>此方法是线程安全的,因为它将锁定实例*</li>
</ul>
<hr>
<pre><code class="language-pascal">function PopEquals(aAnother: pointer; aCompare: TDynArraySortCompare; out aValue): boolean;
</code></pre>
<p>*从队列中按FIFO(先入先出)方式提取一个匹配的项</p>
<ul>
<li>当前<code>pending</code>项与aAnother值进行比较*</li>
</ul>
<hr>
<pre><code class="language-pascal">function WaitPeekLocked(aTimeoutMS: integer; const aWhenIdle: TThreadMethod): pointer;
</code></pre>
<p>*等待从队列中按FIFO(先入先出)方式查找一个项</p>
<ul>
<li>在aTimeoutMS时间内返回一个指向<code>pending</code>项的指针</li>
<li>保持Safe.ReadWriteLock,因此调用者可以检查其内容,然后如果它是预期的项,则调用<code>Pop</code>(),并最终调用Safe.ReadWriteUnlock</li>
<li>如果在时间内没有将任何内容推入队列,则返回nil</li>
<li>此方法是线程安全的,但仅在需要时锁定实例*</li>
</ul>
<hr>

```pascal
function WaitPop(aTimeoutMS: integer; const aWhenIdle: TThreadMethod; out aValue; aCompared: pointer = nil; aCompare: TDynArraySortCompare = nil): boolean;
```
<p>*等待并从队列中按FIFO(先入先出)方式提取一个项</p>
<ul>
<li>如果在指定的aTimeoutMS时间内aValue已被填充了一个<code>pending</code>项,则返回true</li>
<li>如果在时间内没有将任何内容推入队列,或者已调用<code>WaitPopFinalize</code>,则返回false</li>
<li>aWhenIdle可以被分配,例如给VCL/LCL Application.ProcessMessages</li>
<li>可以在返回之前可选地比较<code>pending</code>项(例如,当多个线程将项放入队列时可以使用)</li>
<li>此方法是线程安全的,但仅在需要时锁定实例*</li>
</ul>
<hr>
<pre><code class="language-pascal">procedure Clear;
</code></pre>
<p>*删除当前存储在此队列中的所有项,并清空其<code>capacity</code></p>
<ul>
<li>此方法是线程安全的,因为它将锁定实例*</li>
</ul>
<hr>
<pre><code class="language-pascal">procedure Push(const aValue);
</code></pre>
<p>*将一个项<code>存储</code>到队列中</p>
<ul>
<li>此方法是线程安全的,因为它将锁定实例*</li>
</ul>
<hr>
<pre><code class="language-pascal">procedure Save(out aDynArrayValues; aDynArray: PDynArray = nil); overload;
</code></pre>
<p>*使用存储的队列项初始化一个动态数组</p>
<ul>
<li>aDynArrayValues应是一个在<code>Create</code>中定义的aTypeInfo变量</li>
<li>可以检索一个可选的<code>TDynArray</code>包装器,例如用于二进制或JSON持久化</li>
<li>此方法是线程安全的,并将复制队列数据*</li>
</ul>
<hr>

```pascal
procedure WaitPopFinalize(aTimeoutMS: integer = 100);
```
<p>*确保任何<code>pending</code>或未来的<code>WaitPop</code>()方法立即返回false</p>
<ul>
<li>总是由<code>Destroy</code>析构函数调用</li>
<li>也可以从UI的OnClose事件中调用,以避免任何锁定</li>
<li>此方法是线程安全的,但仅在需要时锁定实例*</li>
</ul>
<hr>
<h3 id="133-tpendingtasklistitem-">1.3.3. TPendingTaskListItem </h3>
<pre><code class="language-pascal">TPendingTaskListItem = packed record
</code></pre>
<p><em>内部项目定义,由</em><em><code>TPendingTaskList</code>存储使用</em></p>
<hr>

```pascal
Task: RawByteString;
```
<p><em>相关联的</em><em><code>task</code>,以原始二进制形式存储</em></p>
<hr>
<pre><code class="language-pascal">Timestamp: Int64;
</code></pre>
<p><em>当TPendingTaskList.GetTimestamp达到此值时,应执行<code>task</code></em></p>
<hr>

### 1.3.4. TPendingTaskList
<pre><code class="language-pascal">TPendingTaskList = class(TObject)
</code></pre>
<p>*线程安全的任务列表,以<code>RawByteString</code>形式存储,并带有时间戳</p>
<ul>
<li>你可以向内部列表添加任务,以在给定延迟后执行,使用类似于post/peek的算法</li>
<li>执行延迟预计不准确,但根据每次NextPendingTask调用和GetTimestamp解析度进行最佳猜测*</li>
</ul>
<hr>
<pre><code class="language-pascal">constructor Create; reintroduce;
</code></pre>
<p><em>默认返回<code>GetTickCount64</code>来初始化列表内存和资源</em></p>
<hr>
<pre><code class="language-pascal">function NextPendingTask: RawByteString; virtual;
</code></pre>
<p>*检索下一个待处理<code>task</code></p>
<ul>
<li>如果当前没有计划中的<code>task</code>,则返回''</li>
<li>返回与指定延迟相对应的下一个堆栈*</li>
</ul>
<hr>
<pre><code class="language-pascal">procedure AddTask(aMilliSecondsDelayFromNow: integer; const aTask: RawByteString); virtual;
</code></pre>
<p><em>从当前时间开始,指定毫秒延迟后<code>Append</code>一个<code>task</code></em></p>
<hr>
<pre><code class="language-pascal">procedure AddTasks(const aMilliSecondsDelays: array of integer; const aTasks: array of RawByteString);
</code></pre>
<p>*指定任务之间的毫秒延迟后<code>Append</code>多个任务</p>
<ul>
<li>第一个提供的延迟将从当前时间开始计算,然后它将指定等待下一个提供<code>task</code>需要多长时间——也就是说,aMilliSecondsDelays不是绝对延迟*</li>
</ul>
<hr>
<pre><code class="language-pascal">procedure Clear; virtual;
</code></pre>
<p><em>清除所有待处理任务</em></p>
<hr>
<pre><code class="language-pascal">property Count: integer read GetCount;
</code></pre>
<p><em>当前定义了多少个待处理任务</em></p>
<hr>
<pre><code class="language-pascal">property Task: TPendingTaskListItemDynArray read fTask;
</code></pre>
<p>*直接低级访问内部<code>task</code>列表</p>
<ul>
<li>警告:此动态数组的长度是列表容量:请使用<code>Count</code>属性来检索存储的确切项数</li>
<li>使用try ... finally Safe.Unlock块中的Safe.Lock/TryLock进行线程安全访问此数组</li>
<li>项目按递增的<code>Timestamp</code>存储,即第一个项目是<code>NextPendingTask</code>方法将返回的下一个项目*</li>
</ul>
<hr>
<pre><code class="language-pascal">property Timestamp: Int64 read GetTimestamp;
</code></pre>
<p>*访问内部<code>TPendingTaskListItem.Timestamp</code>存储的值</p>
<ul>
<li>对应当前时间</li>
<li>默认实现是返回<code>GetTickCount64</code>,在Windows下典型分辨率为16毫秒*</li>
</ul>
<hr>

<h3 id="135-ilockeddocvariant">1.3.5. ILockedDocVariant</h3>
<pre><code class="language-pascal">ILockedDocVariant = interface(IInterface)
</code></pre>
<p>*用于线程安全访问<code>TDocVariant</code>文档的引用计数接口</p>
<ul>
<li>例如,由<code>TLockedDocVariant</code>实现,用于IoC/DI解析</li>
<li>快速且安全地存储任何类似JSON的对象,作为属性/值对,或类似JSON的数组,作为值*</li>
</ul>
<hr>
<pre><code class="language-pascal">function AddExistingProp(const Name: RawUtf8; var Obj: variant): boolean;
</code></pre>
<p>*将现有属性<code>value</code>添加到给定的<code>TDocVariant</code>文档对象</p>
<ul>
<li>如果Name存在,则返回TRUE并将Name/<code>Value</code>对添加到Obj</li>
<li>如果存储的文档中不存在Name,则返回FALSE</li>
<li>此方法在查找Name期间会使用<code>lock</code>,但无论是否返回FALSE,总是会释放<code>lock</code>(参见<code>AddExistingPropOrLock</code>)*</li>
</ul>
<hr>
<pre><code class="language-pascal">function AddExistingPropOrLock(const Name: RawUtf8; var Obj: variant): boolean;
</code></pre>
<p>*将现有属性<code>value</code>添加到给定的<code>TDocVariant</code>文档对象</p>
<ul>
<li>如果Name存在,则返回TRUE并将Name/<code>Value</code>对添加到Obj,使用内部<code>lock</code>确保线程安全</li>
<li>如果存储的文档中不存在Name,则返回FALSE并锁定内部存储:调用者最终应通过<code>AddNewPropAndUnlock</code>()释放<code>lock</code></li>
<li>可以这样使用,以实现线程安全的缓存:</li>
</ul>
<pre><code class="language-pascal">if not cache.AddExistingPropOrLock('Articles',Scope) then
cache.AddNewPropAndUnlock('Articles',GetArticlesFromDB,Scope);
</code></pre>
<p>这里GetArticlesFromDB会在主要<code>lock</code>内部执行</p>
<hr>
<pre><code class="language-pascal">function Copy: variant;
</code></pre>
<p><em>对内部<code>TDocVariant</code>文档对象或数组进行线程安全的复制</em></p>
<hr>
<pre><code class="language-pascal">function Exists(const Name: RawUtf8; out Value: Variant): boolean;
</code></pre>
<p>*按名称检查和返回一个给定的属性</p>
<ul>
<li>如果找到Name,则返回TRUE并将与提供的Name相关联的<code>value</code>填充到<code>Value</code>中,使用内部<code>lock</code>确保线程安全</li>
<li>如果未找到Name,则返回FALSE并释放内部<code>lock</code>:如果你想要添加缺失的<code>value</code>,请使用<code>ExistsOrLock</code>()*</li>
</ul>
<hr>
<pre><code class="language-pascal">function ExistsOrLock(const Name: RawUtf8; out Value: Variant): boolean;
</code></pre>
<p>*按名称检查和返回一个给定的属性</p>
<ul>
<li>如果找到Name,则返回TRUE并将与提供的Name相关联的<code>value</code>填充到<code>Value</code>中,使用内部<code>lock</code>确保线程安全</li>
<li>如果Name不存在,则返回FALSE并设置内部<code>lock</code>:调用者随后应通过<code>ReplaceAndUnlock</code>()释放<code>lock</code>*</li>
</ul>
<hr>

```pascal
function Lock: TAutoLocker;
```
<p><em>对关联的线程安全互斥锁进行低级访问</em></p>
<hr>
<pre><code class="language-pascal">function ToJson(HumanReadable: boolean = false): RawUtf8;
</code></pre>
<p><em>将存储的值保存为UTF-8编码的JSON对象</em></p>
<hr>
<pre><code class="language-pascal">procedure AddItem(const Value: variant);
</code></pre>
<p>*将<code>value</code>添加到内部<code>TDocVariant</code>文档数组</p>
<ul>
<li>不应与其他基于文档的替代方案(如<code>Exists</code>/<code>AddExistingPropOrLock</code>或<code>AddExistingProp</code>)结合使用*</li>
</ul>
<hr>
<pre><code class="language-pascal">procedure AddNewProp(const Name: RawUtf8; const Value: variant; var Obj: variant);
</code></pre>
<p>*将属性<code>value</code>添加到给定的<code>TDocVariant</code>文档对象</p>
<ul>
<li>此方法在调用时不会期望资源被锁定,与<code>AddNewPropAndUnlock</code>不同</li>
<li>将使用内部<code>lock</code>确保线程安全</li>
<li>如果Name已存在,将更新/更改现有的<code>value</code></li>
<li>可以这样使用,以实现线程安全的缓存:</li>
</ul>
<pre><code class="language-pascal">if not cache.AddExistingProp('Articles',Scope) then
cache.AddNewProp('Articles',GetArticlesFromDB,Scope);
</code></pre>
<p>这里GetArticlesFromDB会在主<code>lock</code>之外执行</p>
<hr>
<pre><code class="language-pascal">procedure AddNewPropAndUnlock(const Name: RawUtf8; const Value: variant; var Obj: variant);
</code></pre>
<p>*将属性<code>value</code>添加到给定的<code>TDocVariant</code>文档对象以及内部存储的文档,然后释放之前的<code>lock</code></p>
<ul>
<li>调用此方法之前应由<code>AddExistingPropOrLock</code>()返回false,即在一个已锁定的实例上执行*</li>
</ul>
<hr>
<pre><code class="language-pascal">procedure Clear;
</code></pre>
<p><em>删除所有存储的属性</em></p>
<hr>
<pre><code class="language-pascal">procedure ReplaceAndUnlock(const Name: RawUtf8; const Value: Variant; out LocalValue: Variant);
</code></pre>
<p>*通过属性名称设置<code>value</code>,并设置本地副本</p>
<ul>
<li>可以这样使用,以实现线程安全的缓存:</li>
</ul>
<pre><code class="language-pascal">if not cache.ExistsOrLock('prop',local) then
cache.ReplaceAndUnlock('prop',newValue,local);
</code></pre>
<ul>
<li>调用此方法之前应由<code>ExistsOrLock</code>()返回false,即在一个已锁定的实例上执行</li>
</ul>
<hr>

```pascal
property Value: Variant read GetValue write SetValue;
```
<p>*通过此属性安全地访问文档字段</p>
<ul>
<li>这是此存储的主要入口点</li>
<li>如果在读取时Name不存在,将引发<code>EDocVariant</code>异常</li>
<li>实现类将对variant <code>value</code>进行线程安全的副本*</li>
</ul>
<hr>

<h3 id="136-tlockeddocvariant">1.3.6. TLockedDocVariant</h3>
<pre><code class="language-pascal">TLockedDocVariant = class(TInterfacedObjectWithCustomCreate)
</code></pre>
<p>*允许线程安全地访问<code>TDocVariant</code>文档</p>
<ul>
<li>此类从<code>TInterfacedObjectWithCustomCreate</code>继承,因此您可以定义一个mormot.core.interfaces.pas <code>TInjectableObject</code>的已发布属性为<code>ILockedDocVariant</code>,以便此类可以自动注入*</li>
</ul>
<hr>
<pre><code class="language-pascal">constructor Create(options: TDocVariantOptions); reintroduce; overload;
</code></pre>
<p><em>使用相应的选项初始化线程安全的文档存储</em></p>
<hr>
<pre><code class="language-pascal">constructor Create(options: TDocVariantModel); reintroduce; overload;
</code></pre>
<p><em>从给定的模板初始化线程安全的文档存储</em></p>
<hr>
<pre><code class="language-pascal">constructor Create; overload; override;
</code></pre>
<p>*使用快速的<code>TDocVariant</code>初始化线程安全的文档</p>
<ul>
<li>即调用<code>Create</code>(true)或<code>Create</code>(<code>JSON_FAST</code>)</li>
<li>这将是<code>TInterfacedObjectWithCustomCreate</code>的默认构造函数,例如在IoC/DI解析期间调用*</li>
</ul>
<hr>
<pre><code class="language-pascal">destructor Destroy; override;
</code></pre>
<p><em>销毁存储</em></p>
<hr>
<pre><code class="language-pascal">function AddExistingProp(const Name: RawUtf8; var Obj: variant): boolean;
</code></pre>
<p>*向给定的<code>TDocVariant</code>文档对象添加一个已存在的属性<code>value</code></p>
<ul>
<li>如果Name存在,则返回TRUE并将Name/<code>Value</code>对添加到Obj</li>
<li>如果存储的文档中不存在Name,则返回FALSE</li>
<li>此方法在查找Name期间会使用<code>lock</code>,但无论是否返回FALSE,总是会释放<code>lock</code>(参见<code>AddExistingPropOrLock</code>)*</li>
</ul>
<hr>
<pre><code class="language-pascal">function AddExistingPropOrLock(const Name: RawUtf8; var Obj: variant): boolean;
</code></pre>
<p>*向给定的<code>TDocVariant</code>文档对象添加一个已存在的属性<code>value</code></p>
<ul>
<li>如果Name存在,则返回TRUE并将Name/<code>Value</code>对添加到Obj</li>
<li>如果存储的文档中不存在Name,则返回FALSE,并期望最终调用Lock.Leave或<code>AddNewPropAndUnlock</code>()</li>
</ul>
<hr>
<pre><code class="language-pascal">function Copy: variant;
</code></pre>
<p><em>对内部<code>TDocVariant</code>文档对象或数组进行线程安全的复制</em></p>
<hr>
<pre><code class="language-pascal">function Exists(const Name: RawUtf8; out Value: Variant): boolean;
</code></pre>
<p><em>按名称检查和返回一个给定的属性</em></p>
<hr>
<pre><code class="language-pascal">function ExistsOrLock(const Name: RawUtf8; out Value: Variant): boolean;
</code></pre>
<p>*按名称检查和返回一个给定的属性</p>
<ul>
<li>如果找到,则返回TRUE并返回现有Name的<code>value</code></li>
<li>如果未找到,则返回FALSE,并期望最终调用Lock.Leave或<code>ReplaceAndUnlock</code>()</li>
</ul>
<hr>
<pre><code class="language-pascal">function Lock: TAutoLocker;
</code></pre>
<p><em>对关联的线程安全互斥锁进行低级访问</em></p>
<hr>
<pre><code class="language-pascal">function ToJson(HumanReadable: boolean = false): RawUtf8;
</code></pre>
<p>*将存储的<code>value</code>保存为UTF-8编码的JSON对象</p>
<ul>
<li>仅仅是<code>VariantSaveJson</code>()的包装*</li>
</ul>
<hr>
<pre><code class="language-pascal">procedure AddItem(const Value: variant);
</code></pre>
<p><em>将<code>value</code>添加到内部<code>TDocVariant</code>文档数组</em></p>
<hr>
<pre><code class="language-pascal">procedure AddNewProp(const Name: RawUtf8; const Value: variant; var Obj: variant);
</code></pre>
<p>*向给定的<code>TDocVariant</code>文档对象添加一个属性<code>value</code></p>
<ul>
<li>此方法在调用时不会期望资源被锁定,与<code>AddNewPropAndUnlock</code>不同</li>
<li>将使用内部<code>lock</code>确保线程安全</li>
<li>如果Name已存在,将更新/更改现有的<code>value</code>*</li>
</ul>
<hr>

```pascal
procedure AddNewPropAndUnlock(const Name: RawUtf8; const Value: variant; var Obj: variant);
```
<p><em>向给定的</em><em><code>TDocVariant</code>文档对象和内部存储的文档添加一个属性<code>value</code></em></p>
<hr>
<pre><code class="language-pascal">procedure Clear;
</code></pre>
<p><em>删除所有存储的属性</em></p>
<hr>

```pascal
procedure ReplaceAndUnlock(const Name: RawUtf8; const Value: Variant; out LocalValue: Variant);
```
<p><em>通过属性名称设置</em><em><code>value</code>,并设置本地副本</em></p>
<hr>

```pascal
property Value: variant read GetValue write SetValue;
```
<p>*将通过此属性安全地访问文档字段</p>
<ul>
<li>如果Name不存在,将引发<code>EDocVariant</code>异常</li>
<li>返回的variant结果是副本,不是varByRef,因为副本将更具线程安全性*</li>
</ul>
<hr>
<h3 id="137-tthreadabstract-">1.3.7. TThreadAbstract </h3>
<pre><code class="language-pascal">TThreadAbstract = class(TThread)
</code></pre>
<p>*所有TThread继承类的抽象父类</p>
<ul>
<li>利用跨编译器和跨版本RTL的差异</li>
<li>拥有预期的Start和TerminateSet方法,以及Terminated属性*</li>
</ul>
<hr>

```pascal
procedure Start;
```
<p>*调用此方法以<code>start</code>线程</p>
<ul>
<li>Resume在最新的RTL中已被弃用,因为一些操作系统(例如Linux)没有实现此暂停/恢复功能;我们在此为Delphi的旧版本定义此方法*</li>
</ul>
<hr>
<pre><code class="language-pascal">procedure Terminate; reintroduce;
</code></pre>
<p><em>重新引入以调用TerminatedSet</em></p>
<hr>

```pascal
procedure TerminatedSet; virtual;
```
<p>*正确<code>terminate</code>线程</p>
<ul>
<li>由重新引入的<code>Terminate</code>调用*</li>
</ul>
<hr>
<pre><code class="language-pascal">property Terminated;
</code></pre>
<p><em>定义为public,因为可能用于<code>terminate</code>处理方法</em></p>
<hr>

<h3 id="138-tsynbackgroundthreadabstract">1.3.8. TSynBackgroundThreadAbstract</h3>
<pre><code class="language-pascal">TSynBackgroundThreadAbstract = class(TThreadAbstract)
</code></pre>
<p>*具有自身执行内容的抽象TThread</p>
<ul>
<li>不应直接使用此类,而应使用<code>TSynBackgroundThreadMethodAbstract</code> / <code>TSynBackgroundThreadEvent</code> / <code>TSynBackgroundThreadMethod</code>,并提供更方便的回调*</li>
</ul>
<hr>
<pre><code class="language-pascal">constructor Create(const aThreadName: RawUtf8; const OnBeforeExecute: TOnNotifyThread = nil; const OnAfterExecute: TOnNotifyThread = nil; CreateSuspended: boolean = false); reintroduce;
</code></pre>
<p>*初始化线程</p>
<ul>
<li>可以定义一些回调来嵌套线程执行,例如分配给TRestServer.BeginCurrentThread/EndCurrentThread,或者至少将OnAfterExecute设置为<code>TSynLogFamily.OnThreadEnded</code>*</li>
</ul>
<hr>
<pre><code class="language-pascal">destructor Destroy; override;
</code></pre>
<p>*释放使用的资源</p>
<ul>
<li>调用<code>WaitForNotExecuting</code>(100)以确保正确终结*</li>
</ul>
<hr>
<pre><code class="language-pascal">function SleepOrTerminated(MS: cardinal): boolean;
</code></pre>
<p>*Sleep()的安全版本,不会中断线程进程</p>
<ul>
<li>如果线程已终止,则返回TRUE</li>
<li>如果成功等待了MS毫秒,则返回FALSE*</li>
</ul>
<hr>
<pre><code class="language-pascal">procedure TerminatedSet; override;
</code></pre>
<p>*正确终止线程</p>
<ul>
<li>由重新引入的Terminate调用*</li>
</ul>
<hr>
<pre><code class="language-pascal">procedure WaitForNotExecuting(maxMS: integer = 500);
</code></pre>
<p>*等待Execute/ExecuteLoop结束(即fExecute&lt;&gt;exRun)</p>
<ul>
<li>在循环中调用Sleep(),直到达到超时</li>
<li>例如在<code>Destroy</code>中使用,以避免任何GPF并确保干净地终结*</li>
</ul>
<hr>
<pre><code class="language-pascal">property Pause: boolean read fExecuteLoopPause write SetExecuteLoopPause;
</code></pre>
<p>*临时停止ExecuteLoop的执行,直到设置为false</p>
<ul>
<li>例如可由<code>TSynBackgroundTimer</code>使用,以延迟后台任务的进程*</li>
</ul>
<pre><code class="language-pascal">property ProcessEvent: TSynEvent read fProcessEvent;
</code></pre>
<p>*访问与低级别相关的事件,用于通知后台线程任务执行</p>
<ul>
<li>可以调用ProcessEvent.SetEvent来触发内部处理循环*</li>
</ul>

<h3 id="139-tsynbackgroundthreadmethodabstract">1.3.9. TSynBackgroundThreadMethodAbstract</h3>
<pre><code class="language-pascal">TSynBackgroundThreadMethodAbstract = class(TSynBackgroundThreadAbstract)
</code></pre>
<p>*抽象TThread,能够在其自己的执行内容中运行方法</p>
<ul>
<li>典型用途是用于处理数据或远程访问的后台线程,同时UI将保持响应,通过在循环中运行OnIdle事件:例如,查看mormot.rest.client.pas单元中<code>TRestClientUri.OnIdle</code>如何处理这种情况</li>
<li>不应直接使用此类,而应从中继承并重写Process方法,或使用<code>TSynBackgroundThreadEvent</code> / <code>TSynBackgroundThreadMethod</code>并提供更方便的回调*</li>
</ul>
<hr>
<pre><code class="language-pascal">constructor Create(const aOnIdle: TOnIdleSynBackgroundThread; const aThreadName: RawUtf8; const OnBeforeExecute: TOnNotifyThread = nil; const OnAfterExecute: TOnNotifyThread = nil); reintroduce;
</code></pre>
<p>*初始化线程</p>
<ul>
<li>如果aOnIdle未设置(即等于nil),它将简单地等待后台进程完成,直到<code>RunAndWait</code>()返回</li>
<li>可以定义一些回调来嵌套线程执行,例如分配给TRestServer.BeginCurrentThread/EndCurrentThread*</li>
</ul>
<hr>
<pre><code class="language-pascal">destructor Destroy; override;
</code></pre>
<p><em>终结线程</em></p>
<hr>
<pre><code class="language-pascal">function RunAndWait(OpaqueParam: pointer): boolean;
</code></pre>
<p>*在后台线程中异步启动Process抽象方法</p>
<ul>
<li>等待进程完成,同时调用<code>OnIdle</code>()回调</li>
<li>在后台线程中引发的任何异常都将在调用者线程中转换</li>
<li>如果self未设置,或者从当前正在处理的同一线程中调用(以避免从<code>OnIdle</code>()回调引发的竞态条件),则返回false</li>
<li>当后台进程完成时返回true</li>
<li>OpaqueParam将用于指定后台进程的线程安全内容</li>
<li>此方法是线程安全的,即它将等待由另一个线程启动的任何进程:可以从任何线程调用此方法,即使其主要目的是从主UI线程调用*</li>
</ul>
<hr>
<pre><code class="language-pascal">property OnAfterProcess: TOnNotifyThread read fOnAfterProcess write fOnAfterProcess;
</code></pre>
<p><em>在每个Process之后在Execute中触发的可选回调事件</em></p>
<hr>
<pre><code class="language-pascal">property OnBeforeProcess: TOnNotifyThread read fOnBeforeProcess write fOnBeforeProcess;
</code></pre>
<p><em>在每个Process之前在Execute中触发的可选回调事件</em></p>
<hr>
<pre><code class="language-pascal">property OnIdle: TOnIdleSynBackgroundThread read fOnIdle write fOnIdle;
</code></pre>
<p>*在远程阻塞进程期间循环执行的回调事件,例如,在请求时间较长时刷新UI</p>
<ul>
<li>可以为此属性分配一个回调,例如调用Application.ProcessMessages,在后台线程中执行远程请求,但让UI保持响应:mORMotUILogin.pas中的TLoginForm.OnIdleProcess和OnIdleProcessForm方法将满足此属性的预期</li>
<li>如果<code>OnIdle</code>未设置(即等于nil),它将简单地等待后台进程完成,直到<code>RunAndWait</code>()返回*</li>
</ul>
<hr>
<pre><code class="language-pascal">property OnIdleBackgroundThreadActive: boolean read GetOnIdleBackgroundThreadActive;
</code></pre>
<p>*如果后台线程处于活动状态,并且在处理过程中调用了<code>OnIdle</code>事件,则为TRUE</p>
<ul>
<li>例如,用于确保用户界面消息不会重新进入*</li>
</ul>
<hr>

<h3 id="1310-tsynbackgroundthreadevent">1.3.10. TSynBackgroundThreadEvent</h3>
<pre><code class="language-pascal">TSynBackgroundThreadEvent = class(TSynBackgroundThreadMethodAbstract)
</code></pre>
<p><em>允许后台线程处理方法回调</em></p>
<hr>
<pre><code class="language-pascal">constructor Create(const aOnProcess: TOnProcessSynBackgroundThread; const aOnIdle: TOnIdleSynBackgroundThread; const aThreadName: RawUtf8); reintroduce;
</code></pre>
<p>*初始化线程</p>
<ul>
<li>如果aOnIdle未设置(即等于nil),它将简单地等待后台进程完成,直到RunAndWait()返回*</li>
</ul>
<hr>
<pre><code class="language-pascal">property OnProcess: TOnProcessSynBackgroundThread read fOnProcess write fOnProcess;
</code></pre>
<p>*提供一个在后台线程中执行的方法处理程序</p>
<ul>
<li>由RunAndWait()方法触发 - 该方法将等待直到完成</li>
<li>在RunAndWait()中指定的OpaqueParam将在此处提供*</li>
</ul>
<hr>

<h3 id="1311-tsynbackgroundthreadmethod">1.3.11. TSynBackgroundThreadMethod</h3>
<pre><code class="language-pascal">TSynBackgroundThreadMethod = class(TSynBackgroundThreadMethodAbstract)
</code></pre>
<p><em>允许后台线程处理可变的TThreadMethod回调</em></p>
<hr>
<pre><code class="language-pascal">procedure RunAndWait(Method: TThreadMethod); reintroduce;
</code></pre>
<p>*运行一次提供的TThreadMethod回调</p>
<ul>
<li>使用此方法,而不是继承的<code>RunAndWait</code>()*</li>
</ul>
<hr>

<h3 id="1312-tsynbackgroundthreadprocedure">1.3.12. TSynBackgroundThreadProcedure</h3>
<pre><code class="language-pascal">TSynBackgroundThreadProcedure = class(TSynBackgroundThreadMethodAbstract)
</code></pre>
<p><em>允许后台线程处理过程回调</em></p>
<hr>
<pre><code class="language-pascal">constructor Create(aOnProcess: TOnProcessSynBackgroundThreadProc; const aOnIdle: TOnIdleSynBackgroundThread; const aThreadName: RawUtf8); reintroduce;
</code></pre>
<p>*初始化线程</p>
<ul>
<li>如果aOnIdle未设置(即等于nil),它将简单地等待后台进程完成,直到RunAndWait()返回*</li>
</ul>
<hr>
<pre><code class="language-pascal">property OnProcess: TOnProcessSynBackgroundThreadProc read fOnProcess write fOnProcess;
</code></pre>
<p>*提供一个在后台线程中执行的过程处理程序</p>
<ul>
<li>由RunAndWait()方法触发 - 该方法将等待直到完成</li>
<li>在RunAndWait()中指定的OpaqueParam将在此处提供*</li>
</ul>
<hr>

<h3 id="1313-tsynbackgroundthreadprocess">1.3.13. TSynBackgroundThreadProcess</h3>
<pre><code class="language-pascal">TSynBackgroundThreadProcess = class(TSynBackgroundThreadAbstract)
</code></pre>
<p><em>能够在给定周期速率下运行方法的TThread</em></p>
<hr>
<pre><code class="language-pascal">constructor Create(const aThreadName: RawUtf8; const aOnProcess: TOnSynBackgroundThreadProcess; aOnProcessMS: cardinal; const aOnBeforeExecute: TOnNotifyThread = nil; const aOnAfterExecute: TOnNotifyThread = nil; aStats: TSynMonitorClass = nil; CreateSuspended: boolean = false); reintroduce; virtual;
</code></pre>
<p>*初始化线程以进行周期性任务处理</p>
<ul>
<li>当调用ProcessEvent.SetEvent或自上次处理以来已经过去了aOnProcessMS毫秒周期时,将调用aOnProcess</li>
<li>如果aOnProcessMS为0,将等待直到调用ProcessEvent.SetEvent</li>
<li>可以定义一些回调来嵌套线程执行,例如分配给TRestServer.BeginCurrentThread/EndCurrentThread*</li>
</ul>
<hr>
<pre><code class="language-pascal">destructor Destroy; override;
</code></pre>
<p><em>终结线程并等待其结束</em></p>
<hr>
<pre><code class="language-pascal">property OnException: TNotifyEvent read fOnException write fOnException;
</code></pre>
<p>*当<code>OnProcess</code>引发异常时执行的事件回调</p>
<ul>
<li>提供的Sender参数是引发的异常实例*</li>
</ul>
<hr>
<pre><code class="language-pascal">property OnProcess: TOnSynBackgroundThreadProcess read fOnProcess;
</code></pre>
<p><em>访问周期性任务的实现事件</em></p>
<hr>
<pre><code class="language-pascal">property OnProcessMS: cardinal read fOnProcessMS write fOnProcessMS;
</code></pre>
<p><em>访问周期性任务处理的延迟(以毫秒为单位)</em></p>
<hr>
<pre><code class="language-pascal">property Stats: TSynMonitor read fStats;
</code></pre>
<p>*处理统计信息</p>
<ul>
<li>如果在类构造函数中aStats为nil,则可能为nil*</li>
</ul>
<hr>

<h3 id="1314-tsynbackgroundtimertask">1.3.14. TSynBackgroundTimerTask</h3>
<pre><code class="language-pascal">TSynBackgroundTimerTask = record
</code></pre>
<p><em>由</em><em><code>TSynBackgroundTimer</code>内部注册列表使用</em></p>
<hr>

<h3 id="1315-tsynbackgroundtimer">1.3.15. TSynBackgroundTimer</h3>
<pre><code class="language-pascal">TSynBackgroundTimer = class(TSynBackgroundThreadProcess)
</code></pre>
<p>*能够在后台线程中以周期速率运行一个或多个任务的TThread</p>
<ul>
<li>例如,通过继承的<code>TRestBackgroundTimer</code>,由<code>TRest.TimerEnable</code>/TimerDisable方法使用</li>
<li>每个进程可以有自己的<code>text</code>消息FIFO队列</li>
<li>如果你<code>expect</code>更新某些GUI,你应该使用TTimer组件(例如,周期为200ms),因为<code>TSynBackgroundTimer</code>将使用自己的独立线程*</li>
</ul>
<hr>
<pre><code class="language-pascal">constructor Create(const aThreadName: RawUtf8; const aOnBeforeExecute: TOnNotifyThread = nil; aOnAfterExecute: TOnNotifyThread = nil; aStats: TSynMonitorClass = nil; aLogClass: TSynLogClass = nil); reintroduce; virtual;
</code></pre>
<p>*初始化线程以进行周期性<code>task</code><code>processing</code></p>
<ul>
<li>你可以定义一些回调来嵌套线程执行,例如分配给TRestServer.BeginCurrentThread/EndCurrentThread,如<code>TRestBackgroundTimer.Create</code>所做的那样*</li>
</ul>
<hr>
<pre><code class="language-pascal">destructor Destroy; override;
</code></pre>
<p><em>终结线程</em></p>
<hr>
<pre><code class="language-pascal">function DeQueue(const aOnProcess: TOnSynBackgroundTimerProcess; const aMsg: RawUtf8): boolean;
</code></pre>
<p>*从<code>processing</code>列表中移除一条消息</p>
<ul>
<li>提供的消息将在与aOnProcess相关联的内部FIFO列表中搜索,如果找到则从列表中移除</li>
<li>aOnProcess应通过之前的调用到<code>Enable</code>()方法进行注册</li>
<li>如果成功则返回true,如果提供的消息未注册则返回false*</li>
</ul>
<hr>
<pre><code class="language-pascal">function Disable(const aOnProcess: TOnSynBackgroundTimerProcess): boolean;
</code></pre>
<p>*取消定义一个在周期秒数上运行的<code>task</code></p>
<ul>
<li>aOnProcess应通过之前的调用到<code>Enable</code>()方法进行注册</li>
<li>如果成功则返回true,如果提供的<code>task</code>未注册则返回false</li>
<li>对于mORMot服务上的后台进程,考虑使用<code>TRestServer</code>的TimerEnable/TimerDisable方法及其<code>TSynBackgroundTimer</code>线程*</li>
</ul>
<hr>
<pre><code class="language-pascal">function EnQueue(const aOnProcess: TOnSynBackgroundTimerProcess; const aMsgFmt: RawUtf8; const Args: array of const; aExecuteNow: boolean = false): boolean; overload;
</code></pre>
<p>*在<code>task</code>的下次执行期间添加一条格式化消息进行处理</p>
<ul>
<li>提供的消息将被添加到与aOnProcess相关联的内部FIFO列表中,然后每次调用时作为aMsg参数提供</li>
<li>如果aExecuteNow为true,则不会等待下一个aOnProcessSecs的发生</li>
<li>aOnProcess应通过之前的调用到<code>Enable</code>()方法进行注册</li>
<li>如果成功则返回true,如果提供的<code>task</code>未注册则返回false*</li>
</ul>
<hr>
<pre><code class="language-pascal">function EnQueue(const aOnProcess: TOnSynBackgroundTimerProcess; const aMsg: RawUtf8; aExecuteNow: boolean = false): boolean; overload;
</code></pre>
<p>*在<code>task</code>的下次执行期间添加一条消息进行处理</p>
<ul>
<li>提供的消息将被添加到与aOnProcess相关联的内部FIFO列表中,然后每次调用时作为aMsg参数提供</li>
<li>如果aExecuteNow为true,则不会等待下一个aOnProcessSecs的发生</li>
<li>aOnProcess应通过之前的调用到<code>Enable</code>()方法进行注册</li>
<li>如果成功则返回true,如果提供的<code>task</code>未注册则返回false*</li>
</ul>
<hr>
<pre><code class="language-pascal">function ExecuteNow(const aOnProcess: TOnSynBackgroundTimerProcess): boolean;
</code></pre>
<p>*立即执行一个<code>task</code>,不等待下一个aOnProcessSecs的发生</p>
<ul>
<li>aOnProcess应通过之前的调用到<code>Enable</code>()方法进行注册</li>
<li>如果成功则返回true,如果提供的<code>task</code>未注册则返回false*</li>
</ul>
<hr>
<pre><code class="language-pascal">function ExecuteOnce(const aOnProcess: TOnSynBackgroundTimerProcess): boolean;
</code></pre>
<p>*立即执行一个<code>task</code>,不等待下一个aOnProcessSecs的发生</p>
<ul>
<li>aOnProcess不应通过之前的调用到<code>Enable</code>()方法进行注册*</li>
</ul>
<hr>
<pre><code class="language-pascal">procedure Enable(const aOnProcess: TOnSynBackgroundTimerProcess; aOnProcessSecs: cardinal);
</code></pre>
<p>*定义一个在周期秒数上运行的<code>task</code>的处理方法</p>
<ul>
<li>对于mORMot服务上的后台进程,考虑使用<code>TRest</code>的TimerEnable/TimerDisable方法及其关联的BackgroundTimer线程*</li>
</ul>
<hr>
<pre><code class="language-pascal">procedure WaitUntilNotProcessing(timeoutsecs: integer = 10);
</code></pre>
<p><em>等待直到没有后台<code>task</code>正在处理</em></p>
<hr>
<pre><code class="language-pascal">property Processing: boolean read fProcessing;
</code></pre>
<p><em>如果当前正在处理某些<code>tasks</code>,则返回TRUE</em></p>
<hr>

```pascal
property Task: TSynBackgroundTimerTaskDynArray read fTask;
```
<p><em>对内部</em><em><code>task</code>列表的低级访问</em></p>
<hr>
<pre><code class="language-pascal">property Tasks: TDynArrayLocked read fTasks;
</code></pre>
<p><em>对内部<code>task</code>列表的线程安全包装的低级访问 Low-level access to the internal <code>task</code> list wrapper and safe</em></p>
<hr>
<hr>

<h3 id="1316-tblockingprocess">1.3.16. TBlockingProcess</h3>
<pre><code class="language-pascal">TBlockingProcess = class(TSynEvent)
</code></pre>
<p>*一个信号量,用于等待某个进程完成</p>
<ul>
<li>例如,在mormot.rest.server.pas中的<code>TBlockingCallback</code>中使用</li>
<li>一旦创建,进程将通过WaitFor调用进行阻塞,当进程后台线程调用NotifyFinished时,阻塞将被释放*</li>
</ul>
<hr>
<pre><code class="language-pascal">constructor Create(aTimeOutMs: integer); reintroduce; overload; virtual;
</code></pre>
<p>*初始化信号量实例</p>
<ul>
<li>指定阻塞执行应被视为失败的超时毫秒数周期(如果设置为0,则默认使用3000)</li>
<li>创建一个与之关联的互斥锁,并由该实例拥有*</li>
</ul>
<hr>
<pre><code class="language-pascal">constructor Create(aTimeOutMs: integer; aSafe: PSynLocker); reintroduce; overload; virtual;
</code></pre>
<p>*重写以<code>reset</code>相关参数并初始化信号量实例</p>
<ul>
<li>指定阻塞执行应被视为失败的超时毫秒数周期(如果设置为0,则默认使用3000)</li>
<li>应提供一个关联的互斥锁*</li>
</ul>
<hr>
<pre><code class="language-pascal">destructor Destroy; override;
</code></pre>
<p><em>终结实例</em></p>
<hr>

```pascal
function NotifyFinished(alreadyLocked: boolean = false): boolean; virtual;
```
<p>*当后台进程完成时应该被调用</p>
<ul>
<li>调用者随后将允许其<code>WaitFor</code>方法返回</li>
<li>如果成功则返回TRUE(即状态不是evRaised或evTimeout)</li>
<li>如果实例已经被锁定(例如,从TBlockingProcessPool.FromCallLocked检索时),你可以设置alreadyLocked=TRUE*</li>
</ul>
<hr>
<pre><code class="language-pascal">function Reset: boolean; virtual;
</code></pre>
<p>*只是一个包装器,用于将内部<code>Event</code>状态重置为evNone</p>
<ul>
<li>在成功完成<code>WaitFor</code>/<code>NotifyFinished</code>过程后,可以使用它来重用同一个<code>TBlockingProcess</code>实例</li>
<li>如果成功则返回TRUE(即状态不是evWaiting),将当前状态设置为evNone,并将Call属性设置为0</li>
<li>如果当前正在进行<code>WaitFor</code>过程,则返回FALSE*</li>
</ul>
<hr>

<pre><code class="language-pascal">function WaitFor: TBlockingEvent; reintroduce; overload; virtual;
</code></pre>
<p>*调用以等待<code>NotifyFinished</code>()被调用或触发超时</p>
<ul>
<li>返回进程的最终状态,即evRaised或evTimeOut*</li>
</ul>
<hr>
<pre><code class="language-pascal">function WaitFor(TimeOutMS: integer): TBlockingEvent; reintroduce; overload;
</code></pre>
<p>*调用以等待<code>NotifyFinished</code>()被调用或触发超时</p>
<ul>
<li>返回进程的最终状态,即evRaised或evTimeOut*</li>
</ul>
<hr>

```pascal
procedure Lock;
```
<p><em>只是fSafe^.</em><em><code>Lock</code>的一个包装器</em></p>
<hr>

```pascal
procedure Unlock;
```
<p><em>只是fSafe^.</em><em><code>Unlock</code>的一个包装器</em></p>
<hr>
<pre><code class="language-pascal">property Event: TBlockingEvent read fEvent;
</code></pre>
<p>*进程的当前状态</p>
<ul>
<li>使用<code>Reset</code>方法可以在<code>WaitFor</code>过程后重用此实例*</li>
</ul>
<hr>
<pre><code class="language-pascal">property TimeOutMs: integer read fTimeOutMS;
</code></pre>
<p><em>在构造函数级别定义的超时周期,以毫秒为单位</em></p>
<hr>

<h3 id="1317-tblockingprocesspoolitem">1.3.17. TBlockingProcessPoolItem</h3>
<pre><code class="language-pascal">TBlockingProcessPoolItem = class(TBlockingProcess)
</code></pre>
<p>*在<code>TBlockingProcessPool</code>中使用的信号量</p>
<ul>
<li>此类信号量具有一个Call字段来标识每次执行*</li>
</ul>
<hr>
<pre><code class="language-pascal">property Call: TBlockingProcessPoolCall read fCall;
</code></pre>
<p>*一个唯一标识符,当被<code>TBlockingProcessPool</code>拥有时,用于标识每次执行</p>
<ul>
<li>Reset方法会将此字段恢复为其默认值0,以便重用或重新开始新的执行*</li>
</ul>
<hr>
<p>这样,<code>TBlockingProcessPoolItem</code>类作为 <code>TBlockingProcess</code>的子类,在继承其信号量功能的基础上,增加了 <code>Call</code>属性来支持在 <code>TBlockingProcessPool</code>中的唯一标识,使得在池化管理信号量时能够区分不同的执行实例。通过 <code>Reset</code>方法,可以重置信号量的状态以及 <code>Call</code>属性,以便循环利用。</p>

<h3 id="1318-tblockingprocesspool">1.3.18. TBlockingProcessPool</h3>
<pre><code class="language-pascal">TBlockingProcessPool = class(TSynPersistent)
</code></pre>
<p>*管理一组<code>TBlockingProcessPoolItem</code>实例</p>
<ul>
<li>每次调用将通过唯一的<code>TBlockingProcessPoolCall</code>值进行标识</li>
<li>用于模拟例如从异步事件驱动的DDD进程中的阻塞执行</li>
<li>它还允许重用<code>TEvent</code>系统资源*</li>
</ul>
<hr>
<pre><code class="language-pascal">constructor Create(aClass: TBlockingProcessPoolItemClass = nil); reintroduce;
</code></pre>
<p><em>为给定的实现类设置<code>TBlockingProcessPoolItem.Call</code>并初始化池</em></p>
<hr>
<pre><code class="language-pascal">destructor Destroy; override;
</code></pre>
<p>*终结池</p>
<ul>
<li>也会强制所有挂起的WaitFor触发evTimeOut*</li>
</ul>
<hr>
<pre><code class="language-pascal">function FromCall(call: TBlockingProcessPoolCall; locked: boolean = false): TBlockingProcessPoolItem; virtual;
</code></pre>
<p>*根据其调用标识符检索<code>TBlockingProcess</code></p>
<ul>
<li>可以从异步过程的回调中使用,例如设置继承自<code>TBlockingProcess</code>的一些附加参数,然后调用NotifyFinished来释放调用者的WaitFor</li>
<li>如果leavelocked为TRUE,则返回的实例将被锁定:调用者应在使用后执行result.Unlock或NotifyFinished(true)*</li>
</ul>
<hr>
<pre><code class="language-pascal">function NewProcess(aTimeOutMs: integer): TBlockingProcessPoolItem; virtual;
</code></pre>
<p>*从内部池中预订一个<code>TBlockingProcess</code></p>
<ul>
<li>出错时返回nil(例如,实例正在销毁)</li>
<li>或者返回与此调用对应的阻塞进程实例;其Call属性将标识异步回调的调用,然后在WaitFor之后,应运行Reset方法来释放池的互斥锁*</li>
</ul>
<hr>

<h3 id="1319-tsynparallelprocessthread">1.3.19. TSynParallelProcessThread</h3>
<pre><code class="language-pascal">TSynParallelProcessThread = class(TSynBackgroundThreadMethodAbstract)
</code></pre>
<p><em>执行</em><em><code>TSynParallelProcess</code>过程的线程</em></p>
<hr>

<h3 id="1320-tsynparallelprocess">1.3.20. TSynParallelProcess</h3>
<pre><code class="language-pascal">TSynParallelProcess = class(TSynPersistentLock)
</code></pre>
<p>*允许在线程池中并行执行基于索引的过程</p>
<ul>
<li>将创建自己的线程池,然后将任何方法的工作分配给每个线程执行*</li>
</ul>
<hr>
<pre><code class="language-pascal">constructor Create(ThreadPoolCount: integer; const ThreadName: RawUtf8; const OnBeforeExecute: TOnNotifyThread = nil; const OnAfterExecute: TOnNotifyThread = nil; MaxThreadPoolCount: integer = 32); reintroduce; virtual;
</code></pre>
<p>*初始化线程池</p>
<ul>
<li>可以定义一些回调来嵌套线程执行,例如分配给TRestServer.BeginCurrentThread/EndCurrentThread</li>
<li>最多可以设置MaxThreadPoolCount=32个线程(你可以允许更大的值,但此线程池的意义在于使其进程饱和每个CPU核心)</li>
<li>如果<code>ThreadPoolCount</code>为0,则不会创建线程,进程将在当前线程中执行*</li>
</ul>
<hr>
<pre><code class="language-pascal">destructor Destroy; override;
</code></pre>
<p><em>终结线程池</em></p>
<hr>
<pre><code class="language-pascal">procedure ParallelRunAndWait(const Method: TOnSynParallelProcess; MethodCount: integer; const OnMainThreadIdle: TNotifyEvent = nil);
</code></pre>
<p>*并行运行一个方法,并等待执行完成</p>
<ul>
<li>将在线程上<code>split</code>执行Method</li>
<li>如果在进程中发生任何异常,此方法将引发ESynParallel异常</li>
<li>如果设置了OnMainThreadIdle,当前线程(例如,预期为主UI线程)将不会处理任何事情,但在等待后台线程时调用此事件*</li>
</ul>
<hr>
<pre><code class="language-pascal">property ParallelRunCount: integer read fParallelRunCount;
</code></pre>
<p><em>已激活的线程数</em></p>
<hr>
<pre><code class="language-pascal">property ThreadName: RawUtf8 read fThreadName;
</code></pre>
<p><em>一些<code>text</code>标识符,用于区分每个拥有的线程</em></p>
<hr>
<pre><code class="language-pascal">property ThreadPoolCount: integer read fThreadPoolCount;
</code></pre>
<p><em>当前在此实例线程池中的线程数</em></p>
<hr>
<hr>

<h3 id="1321-tsynthread">1.3.21. TSynThread</h3>
<pre><code class="language-pascal">TSynThread = class(TThreadAbstract)
</code></pre>
<p>*一个简单的TThread,具有在线程上下文中运行的“Terminate”事件</p>
<ul>
<li>TThread.OnTerminate事件在Synchronize()内部运行,因此不符合我们的期望,即在线程上下文中释放它们创建的资源(例如,对于COM对象或某些数据库驱动程序)</li>
<li>由THttpServerGeneric.NotifyThreadStart()内部使用 - 您不应使用受保护的fOnThreadTerminate事件处理程序</li>
<li>还定义了Start方法,以便与旧版本的Delphi兼容*</li>
</ul>
<hr>
<pre><code class="language-pascal">constructor Create(CreateSuspended: boolean); reintroduce; virtual;
</code></pre>
<p><em>初始化线程实例,处于非挂起状态</em></p>
<hr>
<pre><code class="language-pascal">function SleepOrTerminated(MS: cardinal): boolean;
</code></pre>
<p>*Sleep()的安全版本,不会中断线程进程</p>
<ul>
<li>如果线程已终止,则返回TRUE</li>
<li>如果成功等待了MS毫秒,则返回FALSE*</li>
</ul>
<hr>
<pre><code class="language-pascal">property StartNotified: TObject read fStartNotified write fStartNotified;
</code></pre>
<p><em>确保仅在执行了NotifyThreadStart后调用fOnThreadTerminate</em></p>
<hr>

<h3 id="1322-tnotifiedthread">1.3.22. TNotifiedThread</h3>
<pre><code class="language-pascal">TNotifiedThread = class(TSynThread)
</code></pre>
<p>*抽象类,用于实现具有启动/停止通知的线程</p>
<ul>
<li>例如,服务器线程</li>
<li>不要直接使用此类,而应使用<code>THttpServer</code>、<code>THttpApiServer</code>或<code>TWebSocketServer</code>(如mormot.net.websock中定义)*</li>
</ul>
<hr>
<pre><code class="language-pascal">constructor Create(CreateSuspended: boolean; const OnStart, OnStop: TOnNotifyThread; const ProcessName: RawUtf8); reintroduce; virtual;
</code></pre>
<p><em>初始化服务器实例,处于非挂起状态</em></p>
<hr>
<pre><code class="language-pascal">procedure SetServerThreadsAffinityPerCpu( const log: ISynLog; const threads: TThreadDynArray);
</code></pre>
<p>*将每个线程分配给单个逻辑CPU核心</p>
<ul>
<li>例如,对于<code>HTTP</code>服务器,它可能确保具有短生命周期请求和高线程数的更好可扩展性*</li>
</ul>
<hr>
<pre><code class="language-pascal">procedure SetServerThreadsAffinityPerSocket( const log: ISynLog; const threads: TThreadDynArray);
</code></pre>
<p>*将每个线程分配给单个硬件CPU套接字</p>
<ul>
<li>例如,对于<code>HTTP</code>服务器,它可能确保在具有多个物理CPU包的复杂硬件上更好的可扩展性 - 但它非常挑剔,因此仅应在实际硬件上进行适当测试后启用*</li>
</ul>
<hr>
<h3 id="1323-tloggedthread">1.3.23. TLoggedThread</h3>
<pre><code class="language-pascal">TLoggedThread = class(TSynThread)
</code></pre>
<p><em>抽象类,用于实现具有日志通知的线程</em></p>
<hr>
<pre><code class="language-pascal">constructor Create(CreateSuspended: boolean; Logger: TSynLogClass; const ProcName: RawUtf8); reintroduce; virtual;
</code></pre>
<p><em>初始化服务器实例,处于非挂起状态</em></p>
<hr>
<pre><code class="language-pascal">procedure TerminateAndWaitFinished(TimeOutMs: integer = 5000); virtual;
</code></pre>
<p><em>通知线程终止,并等待DoExecute完成</em></p>
<hr>
<pre><code class="language-pascal">property LogClass: TSynLogClass read fLogClass;
</code></pre>
<p><em>关联的日志类</em></p>
<hr>
<pre><code class="language-pascal">property ProcessName: RawUtf8 read fProcessName;
</code></pre>
<p><em>此线程的名称,如提供给<code>SetCurrentThreadName</code>()的</em></p>
<hr>

<h3 id="1324-tloggedworkthread">1.3.24. TLoggedWorkThread</h3>
<pre><code class="language-pascal">TLoggedWorkThread = class(TLoggedThread)
</code></pre>
<p>*一个能够在后台线程中运行某些进程的类</p>
<ul>
<li>具有适当的日志记录和最终结束通知*</li>
</ul>
<hr>
<pre><code class="language-pascal">constructor Create(Logger: TSynLogClass; const ProcessName: RawUtf8; const NameValuePairs: array of const; const OnExecute: TOnLoggedWorkProcess; const OnExecuted: TNotifyEvent = nil); reintroduce; overload;
</code></pre>
<p>*此构造函数将直接在后台启动线程</p>
<ul>
<li>上下文作为具有名称/值对的<code>TDocVariantData</code>对象*</li>
</ul>
<hr>
<pre><code class="language-pascal">constructor Create(Logger: TSynLogClass; const ProcessName: RawUtf8; Sender: TObject; const OnExecute: TNotifyEvent; const OnExecuted: TNotifyEvent = nil); reintroduce; overload;
</code></pre>
<p>*此构造函数将直接在后台启动线程</p>
<ul>
<li>上下文作为常规的TNotifyEvent*</li>
</ul>
<hr>
<hr>

<h3 id="1325-tsynthreadpoolworkthread">1.3.25. TSynThreadPoolWorkThread</h3>
<pre><code class="language-pascal">TSynThreadPoolWorkThread = class(TSynThread)
</code></pre>
<p><em>定义了由</em><em><code>TSynThreadPool</code>使用的工作线程</em></p>
<hr>
<pre><code class="language-pascal">constructor Create(Owner: TSynThreadPool); reintroduce;
</code></pre>
<p><em>异常安全地调用fOwner.Task()来初始化线程</em></p>
<hr>
<pre><code class="language-pascal">destructor Destroy; override;
</code></pre>
<p><em>终结线程</em></p>
<hr>
<pre><code class="language-pascal">procedure Execute; override;
</code></pre>
<p><em>将循环等待任何待处理的任务,并执行fOwner.Task()</em></p>
<hr>
<pre><code class="language-pascal">property Owner: TSynThreadPool read fOwner;
</code></pre>
<p><em>关联的线程池</em></p>
<hr>

<h3 id="1326-tsynthreadpool">1.3.26. TSynThreadPool</h3>
<pre><code class="language-pascal">TSynThreadPool = class(TObject)
</code></pre>
<p>*一个简单的线程池,例如用于快速处理<code>HTTP</code>/1.0请求</p>
<ul>
<li>在Windows上通过I/O完成端口实现,或在Linux/POSIX上通过经典的事件驱动方法实现*</li>
</ul>
<hr>
<pre><code class="language-pascal">constructor Create(NumberOfThreads: integer = 32; aOverlapHandle: THandle = INVALID_HANDLE_VALUE; const aName: RawUtf8 = '');
</code></pre>
<p>*使用提供的线程数初始化线程池</p>
<ul>
<li>抽象Task()虚方法将由其中一个线程调用</li>
<li>一个线程池最多可以关联256个线程</li>
<li>在Windows上,可以可选地接受一个aOverlapHandle - 一个先前使用Windows重叠I/O(IOCP)打开的句柄</li>
<li>在POSIX上,如果aQueuePendingContext=true,则会将待处理上下文存储到内部队列中,以便在可能时处理,直到队列满为止<code>Push</code>()返回true*</li>
</ul>
<hr>
<pre><code class="language-pascal">destructor Destroy; override;
</code></pre>
<p><em>关闭线程池,释放所有关联的线程</em></p>
<hr>
<pre><code class="language-pascal">function Push(aContext: pointer; aWaitOnContention: boolean = false): boolean;
</code></pre>
<p>*让线程池处理一个任务(指定为指针)</p>
<ul>
<li>如果线程池中没有空闲线程可用,并且使用了<code>Create</code>(aQueuePendingContext=false)(调用者应稍后重试),则返回false;如果在<code>Create</code>中aQueuePendingContext为true,或者使用了IOCP,则提供的上下文将被添加到内部列表,并在可能时处理</li>
<li>如果aWaitOnContention默认为false,则当队列满时立即返回;设置aWaitOnContention=true以等待最多<code>ContentionAbortDelay</code>毫秒并重试将任务排队*</li>
</ul>
<hr>
<pre><code class="language-pascal">property ContentionAbortCount: cardinal read fContentionAbortCount;
</code></pre>
<p>*由于线程池争用而被拒绝的任务数量</p>
<ul>
<li>如果此数量较高,请考虑设置更高的线程数,或对Task方法进行分析和调优*</li>
</ul>
<hr>
<pre><code class="language-pascal">property ContentionAbortDelay: integer read fContentionAbortDelay write fContentionAbortDelay;
</code></pre>
<p>*由于争用而拒绝连接的毫秒延迟</p>
<ul>
<li>默认为5000,即在IOCP或aQueuePendingContext内部列表中有可用空间之前等待5秒</li>
<li>在此延迟期间,没有新的连接可用(即不调用Accept),以便负载均衡器可以检测到争用并切换到池中的另一个实例,或者直接客户端最终可能拒绝连接,因此不会开始发送数据*</li>
</ul>
<hr>
<pre><code class="language-pascal">property ContentionCount: cardinal read fContentionCount;
</code></pre>
<p>*线程池等待队列中可用槽位的次数</p>
<ul>
<li>争用不会立即失败,但会重试直到<code>ContentionAbortDelay</code></li>
<li>这里的任何高数值可能需要增加线程数</li>
<li>使用此属性和<code>ContentionTime</code>来计算平均争用时间*</li>
</ul>
<hr>
<pre><code class="language-pascal">property ContentionTime: Int64 read fContentionTime;
</code></pre>
<p>*等待队列中可用槽位的总毫秒数</p>
<ul>
<li>争用不会立即失败,但会重试直到<code>ContentionAbortDelay</code></li>
<li>这里的任何高数值需要对Task方法进行代码重构*</li>
</ul>
<hr>
<pre><code class="language-pascal">property RunningThreads: integer read fRunningThreads;
</code></pre>
<p>*当前在此线程池中处理任务的线程数</p>
<ul>
<li>范围在0..<code>WorkThreadCount</code>之间*</li>
</ul>
<hr>
<pre><code class="language-pascal">property WorkThread: TSynThreadPoolWorkThreads read fWorkThread;
</code></pre>
<p><em>对此线程池中定义的线程的低级访问</em></p>
<hr>
<pre><code class="language-pascal">property WorkThreadCount: integer read fWorkThreadCount;
</code></pre>
<p>*线程池中可用的线程数</p>
<ul>
<li>映射<code>Create</code>()参数,即默认为32*</li>
</ul>
<hr>
<hr>
<h2 id="14-在mormotcorethreads单元中实现的类型">1.4. 在<em>mormot.core.threads</em>单元中实现的类型</h2>

<h3 id="141-tblockingevent">1.4.1. TBlockingEvent</h3>
<pre><code class="language-pascal">TBlockingEvent = ( evNone, evWaiting, evTimeOut, evRaised );
</code></pre>
<p><em></em><em><code>TBlockingProcess</code>实例的当前状态</em></p>
<hr>

<h3 id="142-tblockingprocesspoolcall">1.4.2. TBlockingProcessPoolCall</h3>
<pre><code class="language-pascal">TBlockingProcessPoolCall = type integer;
</code></pre>
<p>*用于标识每个<code>TBlockingProcessPool</code>调用</p>
<ul>
<li>允许匹配给定的<code>TBlockingProcessPoolItem</code>信号量*</li>
</ul>
<hr>

<h3 id="143-tblockingprocesspoolitemclass">1.4.3. TBlockingProcessPoolItemClass</h3>
<pre><code class="language-pascal">TBlockingProcessPoolItemClass = class of TBlockingProcessPoolItem;
</code></pre>
<p><em></em><em><code>TBlockingProcess</code>的类引用类型(元类)</em></p>
<hr>

<h3 id="144-tevent">1.4.4. TEvent</h3>
<pre><code class="language-pascal">TEvent = syncobjs.TEvent;
</code></pre>
<p>*在此处定义以避免在uses子句中显式链接到syncobjs</p>
<ul>
<li>请注意,您可能更希望使用来自mormot.core.os.pas的<code>TSynEvent</code>*</li>
</ul>
<hr>

<h3 id="145-tonidlesynbackgroundthread">1.4.5. TOnIdleSynBackgroundThread</h3>
<pre><code class="language-pascal">TOnIdleSynBackgroundThread = procedure(Sender: TSynBackgroundThreadAbstract; ElapsedMS: integer) of object;
</code></pre>
<p>*在后台线程进行远程阻塞处理期间,由<code>TSynBackgroundThreadAbstract</code>在调用者线程中调用的空闲方法</p>
<ul>
<li>典型用途是运行Application.ProcessMessages,例如对于<code>TRestClientUri.Uri</code>(),即使在远程访问缓慢阻塞的情况下也能提供响应的UI</li>
<li>提供从请求开始经过的时间(以毫秒为单位)(例如,可用于弹出临时等待消息)</li>
<li>在请求开始时调用一次,此时ElapsedMS=0</li>
<li>在请求结束时调用一次,此时ElapsedMS=-1</li>
<li>请参见mORMotUILogin.pas中的TLoginForm.OnIdleProcess和OnIdleProcessForm*</li>
</ul>
<hr>

<h3 id="146-tonloggedworkprocess">1.4.6. TOnLoggedWorkProcess</h3>
<pre><code class="language-pascal">TOnLoggedWorkProcess = procedure(const Context: TDocVariantData) of object;
</code></pre>
<p><em>由</em><em><code>TLoggedWorkThread.Create</code>在后台线程中调用的事件</em></p>
<hr>

<h3 id="147-tonnotifythread">1.4.7. TOnNotifyThread</h3>
<pre><code class="language-pascal">TOnNotifyThread = procedure(Sender: TThread) of object;
</code></pre>
<p><em>事件原型,例如由</em><em><code>TSynBackgroundThreadAbstract</code>和<code>TSynThread</code>回调使用</em></p>
<hr>

<h3 id="148-tonprocesssynbackgroundthread">1.4.8. TOnProcessSynBackgroundThread</h3>
<pre><code class="language-pascal">TOnProcessSynBackgroundThread = procedure(Sender: TSynBackgroundThreadEvent; ProcessOpaqueParam: pointer) of object;
</code></pre>
<p>*由<code>TSynBackgroundThreadEvent</code>调用的后台处理方法</p>
<ul>
<li>当执行Process虚拟方法时,将提供提供给RunAndWait()方法的OpaqueParam参数*</li>
</ul>
<hr>

<h3 id="149-tonprocesssynbackgroundthreadproc">1.4.9. TOnProcessSynBackgroundThreadProc</h3>
<pre><code class="language-pascal">TOnProcessSynBackgroundThreadProc = procedure(ProcessOpaqueParam: pointer);
</code></pre>
<p>*由<code>TSynBackgroundThreadProcedure</code>调用的后台处理过程</p>
<ul>
<li>当执行Process虚拟方法时,将提供提供给RunAndWait()方法的OpaqueParam参数*</li>
</ul>
<hr>

<h3 id="1410-tonsynbackgroundthreadprocess">1.4.10. TOnSynBackgroundThreadProcess</h3>
<pre><code class="language-pascal">TOnSynBackgroundThreadProcess = procedure(Sender: TSynBackgroundThreadProcess) of object;
</code></pre>
<p><em>由</em><em><code>TSynBackgroundThreadProcess</code>定期执行的事件回调</em></p>
<hr>

<h3 id="1411-tonsynbackgroundtimerprocess">1.4.11. TOnSynBackgroundTimerProcess</h3>
<pre><code class="language-pascal">TOnSynBackgroundTimerProcess = procedure(Sender: TSynBackgroundTimer; const Msg: RawUtf8) of object;
</code></pre>
<p>*由<code>TSynBackgroundTimer</code>定期执行的事件回调</p>
<ul>
<li>如果此任务的FIFO中没有待处理消息,则Msg为''</li>
<li>对于此任务的FIFO中的每个待处理消息,都会设置Msg</li>
<li>在mORMot 1中,有一个现在已被移除的TWaitEvent参数*</li>
</ul>
<hr>

<h3 id="1412-tonsynparallelprocess">1.4.12. TOnSynParallelProcess</h3>
<pre><code class="language-pascal">TOnSynParallelProcess = procedure(IndexStart, IndexStop: integer) of object;
</code></pre>
<p>*为<code>TSynParallelProcess</code>实现并行处理过程的回调</p>
<ul>
<li>如果0&lt;=IndexStart&lt;=IndexStop,则应执行一些处理过程*</li>
</ul>
<hr>

<h3 id="1413-tpendingtasklistitemdynarray">1.4.13. TPendingTaskListItemDynArray</h3>
<pre><code class="language-pascal">TPendingTaskListItemDynArray = array of TPendingTaskListItem;
</code></pre>
<p><em>内部列表定义,用于</em><em><code>TPendingTaskList</code>存储</em></p>
<hr>

<h3 id="1414-tsynbackgroundthreadprocessstep">1.4.14. TSynBackgroundThreadProcessStep</h3>
<pre><code class="language-pascal">TSynBackgroundThreadProcessStep = ( flagIdle, flagStarted, flagFinished, flagDestroying );
</code></pre>
<p><em></em><em><code>TSynBackgroundThreadAbstract</code>进程的状态机状态</em></p>
<hr>

<h3 id="1415-tsynbackgroundthreadprocesssteps">1.4.15. TSynBackgroundThreadProcessSteps</h3>
<pre><code class="language-pascal">TSynBackgroundThreadProcessSteps = set of TSynBackgroundThreadProcessStep;
</code></pre>
<p><em></em><em><code>TSynBackgroundThreadAbstract</code>进程的状态机状态集合</em></p>
<hr>

<h3 id="1416-tsynbackgroundtimertaskdynarray">1.4.16. TSynBackgroundTimerTaskDynArray</h3>
<pre><code class="language-pascal">TSynBackgroundTimerTaskDynArray = array of TSynBackgroundTimerTask;
</code></pre>
<p><em>保护Msg[]列表存储</em><em><code>TSynBackgroundTimer</code>的内部注册列表</em></p>
<hr>

<h3 id="1417-tthreaddynarray">1.4.17. TThreadDynArray</h3>
<pre><code class="language-pascal">TThreadDynArray = array of TThread;
</code></pre>
<p><em>TThread的动态数组</em></p>
<hr>

<h3 id="1418-twaitresult">1.4.18. TWaitResult</h3>
<pre><code class="language-pascal">TWaitResult = syncobjs.TWaitResult;
</code></pre>
<p>*在此处定义以避免在uses子句中显式链接到syncobjs</p>
<ul>
<li>请注意,您可能更希望使用来自mormot.core.os.pas的<code>TSynEvent</code>*</li>
</ul>
<h2 id="15-在mormotcorethreads单元中实现的常量">1.5. 在<em>mormot.core.threads</em>单元中实现的常量</h2>

<h3 id="151-threadpool_maxthreads">1.5.1. THREADPOOL_MAXTHREADS</h3>
<pre><code>THREADPOOL_MAXTHREADS = 256;
</code></pre>
<p><em>允许为</em><em><code>TSynThreadPoolWorkThread</code>堆栈分配最多256 * 2MB = 512MB的内存</em></p>
<hr>

<h3 id="152-wrsignaled">1.5.2. wrSignaled</h3>
<pre><code>wrSignaled = syncobjs.wrSignaled;
</code></pre>
<p><em>建议使用mormot.core.os中的</em><em><code>TSynEvent</code>,而不是此处定义的<code>TEvent</code>,以避免在uses子句中显式链接到syncobjs</em></p><br><br>
来源:https://www.cnblogs.com/hieroly/p/18241282
頁: [1]
查看完整版本: mormot.core.threads.pas unit