# thread 库模块帮助文档

## thread 成员列表 <a id="thread" href="#thread">&#x23;</a>

线程函数库,  
这是自动导入的内置库

### thread._callableSerialize <a id="thread._callableSerialize" href="#thread._callableSerialize">&#x23;</a>
界面线程内非窗口对象 _serialize 元方法设定为此函数,可支持跨线程调用,  
绑定此元方法后，对象传入其他线程后所有成员调用都将回到界面线程执行

### thread.add(k,v) <a id="thread.add" href="#thread.add">&#x23;</a>
对参数k指定线程共享变量名称的数值增加参数v指定的计数  
参数v可以使用负数执行减操作

### thread.applyCallWnd(this,wParam,lParam) <a id="thread.applyCallWnd" href="#thread.applyCallWnd">&#x23;</a>
在窗口_WM_THREAD_CALLWND消息回调中响应:  
thread.callWnd,thread.getWnd thread.setWnd调用  
win.form对象默认已应用此函数

### thread.call("函数","owner", ) <a id="thread.call" href="#thread.call">&#x23;</a>
在线程安全模式下执行线程共享区函数  
可以指定一个线程函数，或者用thread.set预加载到共享区的函数名,  
可增加任意个调用参数

### thread.callWnd(hwnd,"成员函数名",... ) <a id="thread.callWnd" href="#thread.callWnd">&#x23;</a>
调用UI线程窗体对象的成员函数  
调用同一线程中的目标窗口函数时，此函数忽略不操作  
参数@1必须指定win.form对象的hwnd句柄  
参数@2指定要调用的成员函数名，支持get元方法ownerCall特性  
可添加不定个数的调用参数

### thread.callWndMeta <a id="thread.callWndMeta" href="#thread.callWndMeta">&#x23;</a>
跨线程传输的窗口对象元表,用于支持跨线程调用

### thread.callable() <a id="thread.callable" href="#thread.callable">&#x23;</a>
开启界面线程非窗口对象的多线程界面回调功能。  
此函数会将对象的_serialize 元方法指定为 thread._callableSerialize,  
用于在界面线程内启用对象跨线程调用支持,注意启用后无法撤消,  
启用此特性后,对象传入其他线程后所有成员调用都将回到界面线程执行,  

参数指定 talbe 类型对象  
如果成功、或者对象已支持跨线程调用返回 true   
失败返回null或false

### thread.callbackInitialize() <a id="thread.callbackInitialize" href="#thread.callbackInitialize">&#x23;</a>
初始化COM套间  
调用此函数以后，创建线程的外部组件应在线程退出前回调 thread.callbackUninitialize  

此函数只能用于：  
thread.tocdecl，tostdcall，tofastcall 等创建的多线程原生回调函数，  
并且只会在第一次成功执行时返回 true，多次调用忽略不执行并返回 null 空值

### thread.callbackUninitialize <a id="thread.callbackUninitialize" href="#thread.callbackUninitialize">&#x23;</a>
原生回调函数指针，  
函数原型为 void __stdcall callbackUninitialize(DWORD dwThreadId)，  

如果dwThreadId参数不是当前线程ID，此函数忽略不执行，  
否则aardio执行一系列资源释放操作，如果之前调用了thread.callbackInitialize 函数，  
那么此函数会负责释放 COM 套间。  

此函数只能用于：  
thread.tocdecl，tostdcall，tofastcall 等创建的多线程原生回调函数，  
如果线程没有调用过 thread.callbackInitialize，不必要调用此函数  

如果没有使用此回调函数释放资源  
aardio 将在线程退出后逐渐回收该线程环境

### thread.create <a id="thread.create" href="#thread.create">&#x23;</a>
创建线程,返回句柄、线程ID  
线程句柄不再使用时,应调用raw.closehandle 函数关闭。  
第一个参数是启动线程的函数,其余参数传递给线程函数。  

注意线程函数有独立的全局变量环境,线程引用的库应当在线程函数内 import

### thread.create(aardio文件路径,调用参数) <a id="thread.create" href="#thread.create">&#x23;</a>
创建线程运行 *.aardio 文件,  
该文件所在目录将被设定为此线程的应用程序根目录,  
该目录下的"/lib/"目录将被设定为用户库目录,  
在线程文件内可使用owner参数获取这里传入的首个调用参数

### thread.create(线程函数,调用参数) <a id="thread.create" href="#thread.create">&#x23;</a>

```aardio

	function( ... ){  
		import win; //线程需要独立引用库  

	},  
	/*传入线程函数的实参写到这里  
线程函数的 owner 参数总是为空*/  
)
```

### thread.createSuspended(suspended,cb) <a id="thread.createSuspended" href="#thread.createSuspended">&#x23;</a>
suspended参数指定thread.create函数创建的线程是否为暂停状态  
如果@cb参数指定了线程函数,则执行线程函数后恢复原来的设置  
其他参数作为回调函数的参数,线程函数的返回值为此函数的返回值  

注意线程函数有独立的全局变量环境,线程引用的库应当在线程函数内 import

### thread.delay() <a id="thread.delay" href="#thread.delay">&#x23;</a>
参数指定延时值，单位毫秒，不可省略，  
导入 win 或 win.ui 库的界面线程内会执行 win.delay，否则执行 sleep 函数。  
调用 win.delay 并且退出消息循环返回 null ，否则总是返回 true。

### thread.get <a id="thread.get" href="#thread.get">&#x23;</a>
从进程共享内存区读取线程共享数据。

### thread.get(uniqueKey) <a id="thread.get" href="#thread.get">&#x23;</a>
n参数 @uniqueKey 可以是数值、字符串或 pointer 类型指针，  
@uniqueKey 是线程共享数据的唯一性标识。  

禁止在任何元方法中使用此函数。

### thread.getExitCode(线程句柄) <a id="thread.getExitCode" href="#thread.getExitCode">&#x23;</a>
获取线程函数返回代码

### thread.getHandle() <a id="thread.getHandle" href="#thread.getHandle">&#x23;</a>
返回当前线程伪句柄  
该句柄仅可在当前线程使用、可复制

### thread.getId() <a id="thread.getId" href="#thread.getId">&#x23;</a>
返回当前线程ID。  
将线程句柄转换为线程 ID 请使用 ::Kernel32.GetThreadId 函数。

### thread.getIdByHandle() <a id="thread.getIdByHandle" href="#thread.getIdByHandle">&#x23;</a>
参数 @1 指定线程句柄，返回对应的线程 ID

### thread.getMainId() <a id="thread.getMainId" href="#thread.getMainId">&#x23;</a>
返回启动当前进程的主线程 ID。  

在开发环境内以线程模式运行 aardio 代码时返回 IDE 主线程。  

默认情况下 aardio 总是在 IDE 进程外运行 aardio 代码，  
除非在 IDE 插件中调用 ide.createThread 在 IDE 线程内启动 aardio 代码。  
任何时候都应当避免使用 ide.createThread 并改用 ide.createProcess 替代。

### thread.getWnd(hwnd,"属性名") <a id="thread.getWnd" href="#thread.getWnd">&#x23;</a>
获取UI线程窗体对象的属性,  
调用同一线程中的目标窗口函数时，此函数忽略不操作

### thread.init(k,v) <a id="thread.init" href="#thread.init">&#x23;</a>
如果参数k指定名称的线程共享变量为空值,  
则初始化该变量值为参数v指定的值

### thread.invoke <a id="thread.invoke" href="#thread.invoke">&#x23;</a>
创建线程但不返回线程句柄，线程句柄已自动关闭。  
成功返回线程 ID。

### thread.invoke(aardio文件路径,调用参数) <a id="thread.invoke" href="#thread.invoke">&#x23;</a>
创建线程运行 *.aardio 文件，不返回线程句柄。  
该文件所在目录将被设定为此线程的应用程序根目录,  
该目录下的"/lib/"目录将被设定为用户库目录,  
在线程文件内可使用owner参数获取这里传入的首个调用参数。

### thread.invoke(线程函数,其他调用参数) <a id="thread.invoke" href="#thread.invoke">&#x23;</a>

```aardio
thread.invoke(   
	function(){  
		/*创建线程但不返回线程句柄。  
注意线程函数有独立的全局变量环境,线程引用的库应当在线程函数内 import*/  
	}  
)
```

### thread.invokeAndWait(func,...) <a id="thread.invokeAndWait" href="#thread.invokeAndWait">&#x23;</a>

```aardio
thread.invokeAndWait(func,...invokeAndWait(  
	function(){  
		import win;  
		/*创建工作线程执行参数@1指定的线程函数,  
参数@1之后的其他可选参数会作为调用线程函数的参数。  
调用并等待线程函数执行完毕,然后获取此线程函数的返回值,  
在界面线程等待时界面仍可响应用户操作，线程函数的返回值会返回给调用线程,  
线程函数拥有独立的全局变量，并应遵守多线程调用规则*/  
	}   
)
```

### thread.invokeEx(线程函数,其他参数) <a id="thread.invokeEx" href="#thread.invokeEx">&#x23;</a>

```aardio
thread.invokeEx(   
	function(){  
		/*创建线程并等待线程执行完成,然后自动关闭线程句柄。  
可用于原生多线程回调函数中创建独立线程以启用 COM 接口,  
注意线程函数有独立的全局变量环境,线程引用的库应当在线程函数内 import*/  
	}  
)
```

### thread.isVar() <a id="thread.isVar" href="#thread.isVar">&#x23;</a>
判断参数 @1 是否 thread.var 创建的线程共享变量。

### thread.lock("临界区名称") <a id="thread.lock" href="#thread.lock">&#x23;</a>
请求锁定并进入临界区  
一个线程进入指定名字临界区,其他线程必须等待,  
直到当前进入临界区的代码调用thread.unlock解锁

### thread.lock("临界区名称",执行函数) <a id="thread.lock" href="#thread.lock">&#x23;</a>

```aardio
thread.lock("临界区名称",function(){  
	/*退出函数自动解锁临界区,返回此函数的返回值*/  
})
```

### thread.main() <a id="thread.main" href="#thread.main">&#x23;</a>
当前线程是否 主线程。

### thread.open <a id="thread.open" href="#thread.open">&#x23;</a>
传入线程 ID 并返回打开的线程句柄。  
将线程句柄转换为线程 ID 请使用 ::Kernel32.GetThreadId 函数。

### thread.open(线程ID,权限,句柄是否可继承) <a id="thread.open" href="#thread.open">&#x23;</a>
打开线程句柄，失败请使用 ..lasterr() 获取错误信息.  
参数二可省略，默认为_THREAD_ALL_ACCESS  
参数三默认为false  
返回的句柄必须使用 raw.closehandle()关闭

### thread.resume(线程句柄) <a id="thread.resume" href="#thread.resume">&#x23;</a>
继续执行

### thread.serializeForm(winform,kernelCall) <a id="thread.serializeForm" href="#thread.serializeForm">&#x23;</a>
用于在 _serialize 元方法内部返回序列化的窗体对象。  
窗体对象的 _serialize 元方法已默认调用此函数。  
显式调用此函数通常用于在线程间序列化对象传递其他窗体对象以替代自身。  
用法可参考 winex.loading 源码。  

参数 winform 必须指定一个窗体对象或者 hwnd 字段值为窗体句柄的表对象。  
kernelCall 参数必须是 _serialize 元方法的回调参数。

### thread.set <a id="thread.set" href="#thread.set">&#x23;</a>
写入一个线程共享数据到进程共享内存区。

### thread.set(uniqueKey,value) <a id="thread.set" href="#thread.set">&#x23;</a>
参数 @uniqueKey 可以是数值、字符串或 pointer 类型指针，  
@uniqueKey 是线程共享数据的唯一性标识。  

参数 @value 指定线程共享数据的值（必须遵守线程间传递数据的规则）。  
赋值为 null 则删除指定的线程共享数据。  

禁止在任何元方法中使用此函数。

### thread.setAffinity(1,) <a id="thread.setAffinity" href="#thread.setAffinity">&#x23;</a>
指定线程在哪个CPU上运行,成功返回原CPU序号,失败返回0,  
参数@1指定CPU,参数@2指定线程句柄  
省略参数@2在设置当前线程

### thread.setWnd(hwnd,"属性名",属性值) <a id="thread.setWnd" href="#thread.setWnd">&#x23;</a>
设置UI线程窗体对象的属性,  
调用同一线程中的目标窗口函数时，此函数忽略不操作

### thread.stillActive() <a id="thread.stillActive" href="#thread.stillActive">&#x23;</a>
线程是否未退出,参数为线程句柄

### thread.stop(退出代码) <a id="thread.stop" href="#thread.stop">&#x23;</a>
终止当前线程。

### thread.suspend(线程句柄) <a id="thread.suspend" href="#thread.suspend">&#x23;</a>
暂停执行  
注意线程是否正在使用互斥锁

### thread.terminate(线程句柄,0) <a id="thread.terminate" href="#thread.terminate">&#x23;</a>
强制终制线程,不推荐使用  
参数二设定返回值,可通过thread.getExitCode获取。

### thread.tocdecl(函数对象,"int()",owner) <a id="thread.tocdecl(函数对象,"int" href="#thread.tocdecl(函数对象,"int">&#x23;</a>
创建多线程回调函数,使用 cdecl 调用约定  
回调线程不是当前线程应使用此函数替换 raw.tocdecl  
回调函数使用独立的线程环境,所有 import 语句必须放在函数体内部  
回调函数在同一线程触发时将复用已创建的线程环境  
可选用参数@3指定回调 owner 参数,该参数必须符合跨线程传递规则  
如果在回调线程内未调用 thread.callbackInitialize,则不能使用 COM 对象  

其他参数、返回值规则与 raw 命名空间下同名函数相同

### thread.tofastcall(函数对象,"int()",owner) <a id="thread.tofastcall(函数对象,"int" href="#thread.tofastcall(函数对象,"int">&#x23;</a>
创建多线程回调函数,使用 ms-fastcall 调用约定  
回调线程不是当前线程应使用此函数替换 raw.tostdcall  
回调函数使用独立的线程环境,所有 import 语句必须放在函数体内部  
回调函数在同一线程触发时将复用已创建的线程环境  
可选用参数@3指定回调 owner 参数,该参数必须符合跨线程传递规则  
如果在回调线程内未调用 thread.callbackInitialize,则不能使用 COM 对象  

其他参数、返回值规则与 raw 命名空间下同名函数相同

### thread.tostdcall(函数对象,"int()",owner) <a id="thread.tostdcall(函数对象,"int" href="#thread.tostdcall(函数对象,"int">&#x23;</a>
创建多线程回调函数,使用 stdcall 调用约定  
回调线程不是当前线程应使用此函数替换 raw.tostdcall  
回调函数使用独立的线程环境,所有 import 语句必须放在函数体内部  
回调函数在同一线程触发时将复用已创建的线程环境  
可选用参数@3指定回调 owner 参数,该参数必须符合跨线程传递规则  
如果在回调线程内未调用 thread.callbackInitialize,则不能使用 COM 对象  

其他参数、返回值规则与 raw 命名空间下同名函数相同

### thread.unlock("临界区名称") <a id="thread.unlock" href="#thread.unlock">&#x23;</a>
解锁释放当前占用的临界区,  
调用thread.lock且指定了执行函数时不需要调用此函数解锁

### thread.unlock() <a id="thread.unlock" href="#thread.unlock">&#x23;</a>
解锁  
等效于thread.unlock("default")

### thread.var <a id="thread.var" href="#thread.var">&#x23;</a>
创建线程共享变量 - 可直接作为调用参数传入其他线程。  
注意 thread.var 不会自动释放，不再使用时一定要调用 release 方法释放

### thread.var() <a id="thread.var" href="#thread.var">&#x23;</a>
[返回对象:threadvarObject](#threadvarObject)

### thread.var(uniqueKeyName,value) <a id="thread.var" href="#thread.var">&#x23;</a>
可选用参数 @uniqueKeyName 指定线程共享变量唯一名称,可选在参数 @value 中指定初始化值,  
如果不指定共享变量名，则自动分配共享变量名,  

线程共享变量不会自动释放,调用 set 函数设为 null 可删除线程变量,  
如果确认没有线程再使用该变量，可调用 relase 函数释放共享变量名,  
thread.var以及 thread.table 自动分配的线程共享变量名上限为  
:0x3FFFFFFFFFFFFC0000000000000 个。  
应及时调用返回对象的 release 函数释放不需要的线程共享变量。

### thread.wait() <a id="thread.wait" href="#thread.wait">&#x23;</a>
等待一个线程句柄返回  
可选使用第二个参数指定超时值（单位毫秒）  
成功返回true,超时返回false;

### thread.waitAll() <a id="thread.waitAll" href="#thread.waitAll">&#x23;</a>
等待一个或多个线程返回  
参数可以是多个线程句柄,或包含多个线程句柄的数组  
可选使用最后一个参数指定超时值（单位毫秒）  
成功返回值为真,失败返回空,  
返回值2为错误类型,该值为字符串"timeout"表示超时

### thread.waitClose() <a id="thread.waitClose" href="#thread.waitClose">&#x23;</a>
等待一个或多个线程返回,并释放所有线程句柄  
参数可以是多个线程句柄,或包含多个线程句柄的数组

### thread.waitOne <a id="thread.waitOne" href="#thread.waitOne">&#x23;</a>
等待一个或多个线程其中一个返回  
如果在界面线程中调用这个函数，会在等待过程中响应用户输入消息。

### thread.waitOne(...,timeout) <a id="thread.waitOne" href="#thread.waitOne">&#x23;</a>
等待一个或多个线程其中一个返回，参数可以是多个线程句柄，  
也可以用参数@1指定一个包含多个线程句柄的数组，  
注意线程句柄总数不能大于64个。  

可选使用最后一个 @timeout 参数指定超时值（单位毫秒）  

成功返回值为完成的句柄在数组中的索引,失败返回空,  
返回值2为错误类型,该值为字符串"timeout"表示超时
