最近在看.Net多线程的时候突然想到PowerBuiler是否支持多线程开发呢?于是Google了下,原来真的可以,不过比较遗憾的是这关于PB多线程方面的资料无论是英文的还是中文的都十分稀缺,完全没有详细的资料可查,连官网都一样,PB自带的帮助文档就更不用说的,简陋啊!!于是自己摸着石头过河,其中也遇到不少莫名其妙的问题,但多数是IDE本身语义检测的缺陷,谁让这不是VS呢?...
----------- 正题分割线 -----------
在PB里要使用多线程开发应用程序必须的3个系统函数:
SharedObjectRegister(string classname,string instancename):
函数功能:共享一个以classname为类型名称的对象,并产生一个新的线程实例,名为instancename.
返回值:枚举类型,Success!表示成功,其他的可以F1.
SharedObjectGet(string instancename,objectinstance):
函数功能:获取SharedObjectRegister创建的线程对象实例的引用,并赋值给objectinstance变量.*objectinstance类型是instancename注册时的类型或继承自它.如果获取不成功,将不对objectinstance操作.
返回值:同上.
SharedObjectUnRegister(string instancename):
函数功能:注销线程实例名为instancename的子线程.
返回值:同上.
还有一个函数SharedObjectDirectory(string instancenames[]{,string classnames[]})函数,得到所有注册的实例名和注册的类型.
PB的多线程有很多限止,以下几个目前发现需要注意的地方:
1.主线程与子线程的资源是相互独立的,子线程可以访问在程序中定义的全局变量,但在线程中对其做的任何修改将不对主线程产生影响.如果有一个全局的引用类型的变量,虽然在主线程中已经实例化但在子线程中访问的时候它是没有被实例化的,这就是它们资源相互独立的地方,主线程与子线程都有相同的全局变量定义,但其作用域只在它们各自的线程内,子线程与子线程之间也是一样,就算是同一个对象里定义了Shared Variables,注册为不同的线程实例,它的资源也是相互独立的,这一点非常的重要.
2.主线程与子线程通讯只能通过NonVisualObject类型或继承自NonVisualObject类型的实例来传递数据,而且传递的数据只能是基本类型的数据,不能传递引用类型的数据,如datastore,transaction等.所有的通讯都只能在这个NonVisualObject类型的中间对象处理,NonVisualObject类型是运行在主线程的.引用类型在哪个线程里Create就是哪一个线程中的资源.
3.操作子线程时,如果是异步调用则必须在函数调用前加Post关键字,如果不加则是同步调用.
4.如果子线程正在执行函数,那么此时不能同步对子线程进行操作,否则将会使线程阻塞造成死锁,所以一定要处理好线程间的资源同步与互斥,这就是为什么有很多人抱怨PB多线程容易使程序挂掉的关键所在.
5.使用SharedObjectUnRegister将线程注销后不会销毁注册的对象实例,而那个对象实例仍然是工作在子线程上过的,不过不能再用SharedObjectGet获取到该线程名的实例引用,但此时可以以这个名字重新注册它,所以当你不再使子线程时应该及时销毁其实例对象以回收内存.
6.子线程Halt了主线程不会退出,相反主线程Halt子线程会退出.
7.SharedObjectRegister注册后的线程可以在程序的任何位置获取,线程名必须是唯一的.
----------- 正题分割线 -----------
在PB里要使用多线程开发应用程序必须的3个系统函数:
SharedObjectRegister(string classname,string instancename):
函数功能:共享一个以classname为类型名称的对象,并产生一个新的线程实例,名为instancename.
返回值:枚举类型,Success!表示成功,其他的可以F1.
SharedObjectGet(string instancename,objectinstance):
函数功能:获取SharedObjectRegister创建的线程对象实例的引用,并赋值给objectinstance变量.*objectinstance类型是instancename注册时的类型或继承自它.如果获取不成功,将不对objectinstance操作.
返回值:同上.
SharedObjectUnRegister(string instancename):
函数功能:注销线程实例名为instancename的子线程.
返回值:同上.
还有一个函数SharedObjectDirectory(string instancenames[]{,string classnames[]})函数,得到所有注册的实例名和注册的类型.
PB的多线程有很多限止,以下几个目前发现需要注意的地方:
1.主线程与子线程的资源是相互独立的,子线程可以访问在程序中定义的全局变量,但在线程中对其做的任何修改将不对主线程产生影响.如果有一个全局的引用类型的变量,虽然在主线程中已经实例化但在子线程中访问的时候它是没有被实例化的,这就是它们资源相互独立的地方,主线程与子线程都有相同的全局变量定义,但其作用域只在它们各自的线程内,子线程与子线程之间也是一样,就算是同一个对象里定义了Shared Variables,注册为不同的线程实例,它的资源也是相互独立的,这一点非常的重要.
2.主线程与子线程通讯只能通过NonVisualObject类型或继承自NonVisualObject类型的实例来传递数据,而且传递的数据只能是基本类型的数据,不能传递引用类型的数据,如datastore,transaction等.所有的通讯都只能在这个NonVisualObject类型的中间对象处理,NonVisualObject类型是运行在主线程的.引用类型在哪个线程里Create就是哪一个线程中的资源.
3.操作子线程时,如果是异步调用则必须在函数调用前加Post关键字,如果不加则是同步调用.
4.如果子线程正在执行函数,那么此时不能同步对子线程进行操作,否则将会使线程阻塞造成死锁,所以一定要处理好线程间的资源同步与互斥,这就是为什么有很多人抱怨PB多线程容易使程序挂掉的关键所在.
5.使用SharedObjectUnRegister将线程注销后不会销毁注册的对象实例,而那个对象实例仍然是工作在子线程上过的,不过不能再用SharedObjectGet获取到该线程名的实例引用,但此时可以以这个名字重新注册它,所以当你不再使子线程时应该及时销毁其实例对象以回收内存.
6.子线程Halt了主线程不会退出,相反主线程Halt子线程会退出.
7.SharedObjectRegister注册后的线程可以在程序的任何位置获取,线程名必须是唯一的.
----------- Sample code -----------
//将w_ThreadTest窗口设为回调对象的父对象 *明义上
QueryCallBack.of_SetParent(Parent)
新建6个NonVisualObject对象:
nvo_ThreadBase //用于创建线程的基类对象.
nvo_ExpThread //导出线程,继承自nvo_ThreadBase
nvo_QueryThread //查询线程,继承自nvo_ThreadBase
nvo_CallBackBase //线程的回调基类对象
nvo_ExpCallBack //导出线程回调对象,继承自nvo_CallBack
nvo_QueryCallBack //查询线程回调对象,继承自nvo_CallBa