Chinaunix首页 | 论坛 | 博客
  • 博客访问: 4736754
  • 博文数量: 206
  • 博客积分: 5240
  • 博客等级: 大校
  • 技术积分: 3224
  • 用 户 组: 普通用户
  • 注册时间: 2010-08-12 21:40
文章分类

全部博文(206)

文章存档

2013年(13)

2012年(8)

2011年(33)

2010年(152)

我的朋友

分类: 敏捷开发

2010-11-23 22:54:56

快手内核库 多线程函数

1.创建线程基础函数
thread.create("线程函数","线程函数参数" ) = 创建线程,返回句柄、线程ID;第一个参数是启动线程的函数,其余参数传递给线程函数;注意线程函数必须使用独立的闭包,import等语句应置于函数内部。
                              线程句柄不再使用时,应调用raw.closehandle("线程句柄“)函数关闭。

*
thread.create(.(aau文件路径,调用参数) = 创建线程运行 *.aau 文件,该文件所在目录将被设定为此线程的应用程序根目录,该目录下的"\lib\"目录将被设定为用户库目录.

thread.create_suspended=true —— 设置创建线程时是否暂停执行(必须在创建线程之前才有效

2.线程加锁解锁
thread.lock("临界区名称") =  加锁
用以避免多个线程同时执行加锁范围内的代码。
thread.unlock("临界区名称") = 解锁
thread.lock() =  加锁, 等效于thread.lock("default")
thread.unlock()  = 解锁, 等效于thread.unlock("default")

3.线程暂停继续执行
thread.resume(*线程句柄*) = 继续执行
thread.suspend(*线程句柄*) = 暂停执行,注意线程是否正在使用互斥锁

4.终止线程
thread.stop(*退出代码*) = 终止当前线程。
thread.terminate(*线程句柄*,0) = 强制终制线程,不推荐使用, 参数二设定返回值,可通过thread.getExitCode获取。

5.线程操作
thread.call("__/*请输入函数名字*/","owner", ) = 执行线程共享区函数
thread.getExitCode(__/*线程句柄*/) = 获取线程函数返回代码 (返回线程的退出返回值)
thread.getMainId() = 返回主前线程ID
thread.getId() = 返回当前线程ID

6.线程储存
thread.set("标志键", ) = 写入一个值到进程共享内存区
标志键可以是数值、字符串等常量、赋值为null则删除该共享键值对此函数禁止在任何元方法中使用。
thread.get("标志键") = 从进程共享内存区读取一个值
标志键可以是数值、字符串等常量, 此函数禁止在任何元方法中使用。

thread.tostdcall(.(函数对象,"void()") = 创建跨线程回调函数,使用stdcall调用约定,回调线程不是当前线程应使用此函数替换raw.tostdcall,回调函数使用独立的线程环境,所有import语句必须放在函数体内部
thread.tocdecl(.(函数对象,"void()") = 创建跨线程回调函数,使用cdecl调用约定,回调线程不是当前线程应使用此函数替换raw.tocdecl,回调函数使用独立的线程环境,所有import语句必须放在函数体内部

7.线程拓展
thread.waitAll = function(...){
return threadwait(1,...);
}
thread.waitOne = function(...){
return threadwait(0,...);
}
thread.wait  = function(handle,ms=0xFFFFFFFF){
return WaitForSingleObject(handle,ms);
}

thread.wait(”线程句柄“,"超时时间") //等待一个线程执行完成
thread.waitOne( "线程句柄 ","等待超时时间") //等待其中任意一个线程执行完成
thread.waitAll( "线程句柄" ,"超时时间") //等待所有线程执行完成
上面指的多个线程句柄可以是多个参数,也可以是包含多个线程句柄的table数组。


thread.setAffinity(__,2) = 指定线程在哪个CPU上运行
thread.setAffinity(__) = 指定线程在CPU 1上运行 

线程共享表(thread.table)

thread.table = 线程共享表
thread.table("table_name") = 创建多线程共享table
thread.table() = thread_table.
?thread.table =  thread_table.
thread_table.get("键名") = 读取成员值
thread_table.set("键名",__/*值*/) = 写入成员值
thread_table.getByNamespace("__/*指定表内名字空间路径*/") = 在指定表查找并返回成员
thread_table.setByNamespace("__/*指定表内名字空间路径*/",新值) = 参数一指定表内名字空间路径,如果不存在则则创建此表内名字空间,\n支持索引操作符,可以使用[]空索引实现在数组尾部添加值\n参数二指定需要设置的值,如果不指定则创建空表并赋值
thread_table.lenByNamespace("__/*指定表内名字空间路径*/") = 返回指定元素长度
thread_table.next(.() = 获取table的第一个键值对元素
thread_table.next(.( key ) = 迭代获取table的下一个键值对元素
thread_table.tostring(__) = 获取table的字符串表达式
thread_table.concat(.( tab2 ) = 拼接多个table对象
thread_table.insert(.(要插入的值,要插入的位置 ) = 插入元素到指定位置
thread_table.insert(.(要插入的值 ) = 插入元素到table头部
thread_table.remove(.(位置 ) = 在表中指定位置移除元素
thread_table.remove(.( ) = 在table头部移除元素
thread_table.push(.(__) = 在顺序数组尾部压入一个或多个元素,返回数组大小
thread_table.push(.(__v1,v2,v3,...) = 在顺序数组尾部压入多个元素,返回数组大小
thread_table.pop(__) = 在顺序数组尾部弹出一个或多个元素并作为返回值
thread_table.sort(.( ) = 排序
thread_table.sort(.( comProc ) = 排序,comProc指定用于比较元素大小的函数
thread_table.reverse(__) =  table数组倒序排列。
thread_table.range(__) =  返回table数组的最小索引,最大索引\nmin,max=tab.range();
thread_table.unpack(__) =  返回表中所有的元素\na,b,c,d,e = tab.unpack();
thread_table.left(len__) = 返回table对象左侧开始返回指定个数的元素。
thread_table.right(len__ = 返回table对象右侧开始返回指定个数的元素 
thread_table.len() = 返回table长度
thread_table.count() = 获取table成员总数
thread_table.each = @for( k,v in ??.each() ){
__ 
}

快手拓展库 多线程函数
1。线程命令 (thread.command库)
响应式编程,也可以叫命令式编程,也就是说每个线程都可以发送命令,每个线程也都可以接收命令,发送命令的人不关心你怎么处理,接收命令的人不关心数据是怎么来的,这样就实现了逻辑解耦,线程的职责也就更清晰。
UI线程用  thread.command 响应命令操作控件

thread.command.post(.(窗口句柄,"命令函数名",其他参数) = 不阻塞调用跨线程命令 
thread.command.post(.("命令函数名",其他参数) = 不阻塞调用跨线程命令,\n不指定窗口句柄,所有同名的线程命令函数都会被调用

thread.command.send(.(窗口句柄,"命令函数名",其他参数) = 阻塞调用跨线程命令,\n可获取回调函数的数值返回值
thread.command.send(.("命令函数名",其他参数) = 阻塞调用跨线程命令\n不指定窗口句柄,所有同名的线程命令函数都会被调用,\n可获取最后一个回调函数的数值返回值

thread.command(.(窗口对象) = 创建线程命令对象\n省略参数则创建 message only window,\n该对象定义的成员函数,都可在其他线程中用 thread.command.post()调用
thread.command() = !thread_command.

!thread_command.自定义函数名 = @.命令函数 = function(__/*支持不定个数参数*/){
 }
!thread_command._form = 窗体对象\n!winform.
_WM_THREAD_COMMAND=@0x4CC/*_WM_THREAD_COMMAND*/

示例1 

  1. import win.ui;
  2. /*DSG{{*/
  3. var winform = ..win.form( right=599;text="多线程命令";bottom=399 )
  4. winform.add(
  5. edit={ bottom=269;right=465;left=54;multiline=1;top=51;z=1;edge=1;cls="edit" }
  6. )
  7. /*}}*/

  8. import thread.command;
  9. 临听器 = thread.command()
  10. 临听器.发现了 = function(idx){
  11.     winform.edit.appendText("发现了:",idx,'\r\n')
  12. }

  13. thread.create(
  14.     function(num){
  15.         import thread.command;
  16.         for(i=1;num;1){
  17.             //调用其他线程的命令
  18.             thread.command.post("发现了",i)
  19.         }    
  20.     },20//给线程函数传参
  21. )    

  22. winform.show()
  23. win.loopMessage();
示例2 线程命令订阅模式

  1. //线程命令订阅模式
  2. import win.ui;
  3. /*DSG{{*/
  4. var winform = ..win.form( bottom=399;parent=...;right=599;text="AAuto Form" )
  5. winform.add(
  6. edit={ bottom=273;right=521;left=66;multiline=1;top=52;z=1;edge=1;cls="edit" }
  7. )
  8. /*}}*/

  9. import thread.command;
  10. var 订阅者 = thread.command();
  11. 订阅者.自定义线程命令 = function(...){
  12.     winform.edit.appendText('\n',...) //将参数追加输出到文本框
  13. }
  14. 订阅者.自定义线程命令2 = function(...){
  15.     winform.edit.appendText('\n',...) //将参数追加输出到文本框
  16. }
  17.  
  18. //创建线程
  19. thread.create(
  20.     function(hwnd){
  21.     
  22.         import thread.command
  23.         
  24.         //如果不指定窗口,所有订阅了此命令的窗口相应函数都会被调用
  25.         thread.command.post("自定义线程命令","线程调用",",线程调用参数2",'\r\n')
  26.         
  27.         //也可以显式指定窗口,仅触发指定窗口的命令
  28.         thread.command.post(hwnd,"自定义线程命令2","线程调用",'\r\n')
  29.         
  30.     },订阅者._form.hwnd
  31. )

  32. winform.show()
  33.  
  34. win.loopMessage();
示例3 多线程采集网址

  1. import win.ui;
  2. /*DSG{{*/
  3. var winform = ..win.form( bottom=400;parent=...;right=600;text="AAuto Form";scroll=1 )
  4. winform.add(
  5. listview={ bgcolor=16777215;bottom=354;right=527;left=26;top=24;z=1;edge=1;cls="listview" }
  6. )
  7. /*}}*/

  8. winform.show();

  9. //列标题
  10. winform.listview.insertColumn("id",30,1);
  11. winform.listview.insertColumn("url",300,2);

  12. import thread.command;
  13. var 订阅者 = thread.command( winform );
  14. 订阅者.send = function(str){
  15.     var i=winform.listview.addItem();
  16.     winform.listview.setItemText(tostring(i),i,1);
  17.     winform.listview.setItemText(str,i,2);
  18. }

  19. var gjz="aauto";
  20. for(i=1;10;1){
  21.     var url=""+gjz+"&usm=1&pn="+i*10;
  22.     thread.create(function(url){
  23.         import thread.command;
  24.         import inet.whttp;
  25.         var http=inet.whttp();
  26.         var html=http.get(url);
  27.         if(html){
  28.             for url in string.gmatch(html,'span class=\"g\"\>(.*?)\/'){
  29.                 thread.command.post("send",url);
  30.             }
  31.         }
  32.     },url)
  33.     win.delay(1000);
  34. }

  35. win.loopMessage();
  36. return winform,wb;
2。事件对象(thread.event) ——— 处理主线程与子线程同步
thread.event = 事件同步对象支持库,可跨进程、跨线程使用.
thread.event("事件对象名称","默认自动置位”,“事件未触发”) = 创建或打开已存在的命名事件对象;参数2是否手动复原信号状态,初始状态0,默认自动复原;参数3为事件触发状态,默认未触发)
                   参数( 名称,是否手动复原信号状态,初始状态0)                                                     参数2, 参数3 是可选参数,仅在创建新事件对象是起作用.

thread_event.close() = 关闭事件对象
                                  该函数并不关闭信号量内核对象
                                  当所有引用内核对象的对象关闭,内核对象自动释放
                                  如果没有手工调用此函数,则线程结束时自动调用.


thread_event.conflict = 如果事件对象已存在,此属性为真值
                                  否则为空值

thread_event.set() = 触发事件,设置事件的状态为有信号状态(每次触发后,必有一个或多个处于等待状态下的线程变成可调度状态),
                               退出所有等待该事件对象信号的函数

thread_event.reset() = 将事件设为末触发,事件对象设置为无信号状态,
                                 如果创建事件对象时并未设定手动复位,此函数不需要手动调用.

thread_event.pulse() = 设置事件对象为有信号状态,并释放某些等待线程
                                  然后设置该事件无效(无信号状态)

thread_event.wait() = 等待事件到有信号状态,
                                 可选增加一个参数指定超时,以毫秒为单位
                                 在UI线程中应使用非阻塞的waitOne()函数替代


thread_event.waitOne() = 等待事件到有信号状态,
                                      可选增加一个参数指定超时,以毫秒为单位

示例1

  1. //使用事件对象同步

  2. import thread.event;
  3. evt = thread.event("事件对象名称 GUID:32DA0FC7-A96D-4850-9A28-DA1DD4464B44")

  4. io.open()
  5. thread.create(
  6.     function(){
  7.         import thread.event;
  8.         evt = thread.event("事件对象名称 GUID:32DA0FC7-A96D-4850-9A28-DA1DD4464B44")
  9.         
  10.         io.print("工作线程:","不客气,您先吧")
  11.         sleep(1000)
  12.         evt.set()
  13.         evt.wait()
  14.         
  15.         ..io.print("工作线程:您可真啰嗦")
  16.         sleep(1000)
  17.         evt.set()
  18.         evt.wait()
  19.         
  20.         ..io.print("工作线程:无语,很无语............")
  21.         sleep(1000)
  22.         evt.set()
  23.     }
  24. )


  25. io.print("主线程: 您先请")
  26. thread.wait( evt ) //也可以作为thread.wait()的参数使用
  27. io.print("主线程:那我就不客气了......#_#~!@")

  28. io.print("主线程:还是您先吧")
  29. evt.set()
  30. evt.wait();

  31. io.print("主线程:小子欠抽是吧?...............")
  32. evt.set()
  33. evt.wait();

  34. io.print("完了完了............")
示例2

  1. //定时执行线程任务

  2. import win.ui;
  3. /*DSG{{*/
  4. var winform = win.form(parent=...; text="使用thread.event创建定时执行任务的线程";right=349;bottom=211 )
  5. winform.add(
  6. trackbar={ bottom=82;max=1000;text="trackbar";left=15;top=52;z=2;right=319;min=500;cls="trackbar" };
  7. lbTip={ bottom=103;text="";left=26;right=100;top=85;z=3;transparent=1;cls="static" };
  8. static={ bottom=44;align="center";text="";left=138;top=13;center=1;z=5;right=309;edge=1;cls="static" };
  9. btnStart={ bottom=155;text="启动定时线程";left=61;top=113;z=1;right=181;cls="button" };
  10. btnStop={ disabled=1;bottom=155;right=312;left=192;top=113;z=4;text="结束定时线程";cls="button" }
  11. )
  12. /*}}*/

  13. task_t = function(hwnd,ms){
  14.     import win;
  15.     import thread.event;
  16.     
  17.     var evt = thread.event("定时事件 GUID:32DA0FC7-A96D-4850-9A28-DA1DD4464B44")
  18.     while( ! evt.wait(ms) ){
  19.         win.setText(hwnd,tostring( time() ) )
  20.     }
  21.     io.print("任务已完成")
  22. }

  23. import thread.event;
  24. var evtTask = thread.event("定时事件 GUID:32DA0FC7-A96D-4850-9A28-DA1DD4464B44",false)

  25. winform.btnStart.oncommand = function(id,event){

  26.     winform.btnStart.disabled = true;
  27.     winform.btnStop.disabled = false;
  28.     winform.trackbar.disabled = true;
  29.     
  30.     hThread = thread.create(task_t,winform.static.hwnd,winform.trackbar.pos);
  31.     thread.waitOne(hThread)
  32.     
  33.     winform.btnStart.disabled = false;
  34.     winform.btnStop.disabled = true;
  35.     winform.trackbar.disabled = false;
  36. }

  37. winform.btnStop.oncommand = function(id,event){
  38.     evtTask.set();//使事件对象切换为有信号状态,使wait函数退出
  39. }

  40. winform.trackbar.oncommand = function(id,event,pos){
  41.     winform.lbTip.text = owner.pos + "毫秒"
  42. }

  43. winform.show()
  44. win.loopMessage();

3。线程互斥量(process.mutex) ——— 确保一个线程独占一个资源的访问。并且互斥量可以用于不同进程中的线程互斥访问资源。
                                                    互斥体有一点象thread.lock()创建的线程临界锁, 不同的是他可以跨进程互斥.
                                                     互斥体虽然能象原子窗体那样限制应用程序仅创建一个实例,但是他不能自动激活原来的窗体, 所以一般推荐使用原子窗体.

process.mutex("互斥体唯一名称") = @mutex=process.mutex("__/*输入唯一标识字符串\n建议使用GUID生成Globally Unique Identifier(全球唯一标识符) */")\nif( mutex.conflict ){\n io.print("互斥体已存在",mutex.handle)\n}\nmutex.close();
mutex.close()=关闭互斥体句柄\n该函数并不关闭互斥体创建的内核对象\n当所有引用内核对象的对象关闭,内核对象自动释放
mutex.conflict = 如果互斥体已存在,此属性为真值\n否则为空值
mutex.release() =  线程在处理完共享资源后,\n应在离开时调用此函数释放互斥体所有权
mutex.wait() = 等待并获取互斥体独占所有权,\n可选增加一个参数指定超时,以毫秒为单位\n注意此函数应与release()函数配对使用\n在UI线程中应使用非阻塞的waitOne()函数替代
mutex.waitOne() = 等待并获取互斥体独占所有权,\n可选增加一个参数指定超时,以毫秒为单位\n注意此函数应与release()函数配对使用

示例1 限制开启程序个数
  1. import win.ui;
  2. import process.mutex
  3. /*DSG{{*/
  4. var winform = win.form(parent=...; text="AAuto Form";right=349;bottom=249 )
  5. winform.add( )
  6. /*}}*/

  7. //创建互斥体
  8. mutex=process.mutex("建议创建一个GUID作为唯一标识")
  9. if( mutex.conflict ){
  10.     winform.msgbox("该程序仅允许运行一个实例" )
  11.     mutex.close()
  12.     return;
  13. }

  14. winform.show()
  15. win.loopMessage();

  16. //程序退出再释放互斥体
  17. mutex.close();
示例2 实现进程退出后再运行别的进程文件
代码复制到工程 main.aau 中生成EXE后再运行测试下例
  1. import win.ui;
  2. /*DSG{{*/
  3. mainForm = ..win.form( right=600;bottom=400;text="test mutex" )
  4. mainForm.add( )
  5. /*}}*/

  6. mainForm.show()

  7. import process.mutex;
  8. mutex = process.mutex("test mutex")

  9. if( mutex.conflict ) {

  10.     mainForm.text = "正在等待前面的进程退出"
  11.     mutex.waitOne()
  12.     
  13.     mainForm.text = "xx进程已退出"
  14. }
  15. else {
  16.     import process;
  17.     import fsys;
  18.     
  19.     //复制自己到临时目录
  20.     var tempPath = fsys.joinpath( fsys.getTempDir(),io._exefile );
  21.     fsys.copy( io._exepath, tempPath );

  22.     process.execute(tempPath);
  23.     mainForm.text = "请关闭程序"
  24. }

  25. win.loopMessage();
  26. mutex.close();

4。信号量(thread.semaphore) ——— 在经典多线程问题中设置一个信号量和一个关键段。用信号量处理主线程与子线程的同步,用关键段来处理各子线程间的互斥。

thread.semaphore("信号量对象名称__",10) = 创建信号量同步对象 参数3是可选参数,默认值等于最大资源计数; 参数2,参数3仅在首次创建该事件对象是起作用.
                          参数( 名称,最大资源计数,初始空闲资源计数0)
                                                   
thread_semaphore.close() = 关闭信号量对象\n该函数并不关闭信号量内核对象\n当所有引用内核对象的对象关闭,内核对象自动释放
thread_semaphore.conflict = 如果信号量对象已存在,此属性为真值\n否则为空值
thread_semaphore.release() =  线程在处理完共享资源后,\n应在离开时调用此函数将可用资源计数加1\n可在参数中指定要释放的资源计数(默认为1)\n第一个返回值表示函数执行是否成功,\n第二个返回值为原来的资源计数
thread_semaphore.wait() = 等待可用资源计数大于0,\n可选增加一个参数指定超时,以毫秒为单位\n注意此函数应与release()函数配对使用\n在UI线程中应使用非阻塞的waitOne()函数替代
thread_semaphore.waitOne() = 等待可用资源计数大于0,\n可选增加一个参数指定超时,以毫秒为单位\n注意此函数应与release()函数配对使用
thread.semaphore = 信号量同步对象支持库\n可跨进程、跨线程使用

示例

  1. //计数信号量同步演示
  2. import thread.semaphore
  3. semaphore = thread.semaphore("事件对象名称",2);

  4. func_t = function(){
  5.     import thread.semaphore
  6.     semaphore = thread.semaphore("事件对象名称",2);    
  7.     
  8.     io.print('我在等待机会') sleep(1)
  9.     semaphore.wait();
  10.     io.print("机会来了,我正在占用资源......")
  11.     sleep(2000)
  12.     semaphore.release()
  13.     
  14.     io.print("已释放资源......") sleep(1)
  15. }

  16. io.open()
  17. io.print("机会只有两个,但是你们都想要.......")
  18. io.print("---------------")

  19. import thread.manage
  20. manage = thread.manage()

  21. for(i=1;10;1){
  22.     manage.create( func_t )
  23.     sleep(100)
  24. }
  25.  
  26. manage.waitClose();
  27. io.print("---------------")
  28. io.print("万里长征终于走完了.......")





//线程库扩展模块;
::WaitForSingleObject := ::Kernel32.api("WaitForSingleObject", "INT(pointer hHandle,INT dwMilliseconds)");
::WaitForMultipleObjects := Kernel32.api("WaitForMultipleObjects", "INT(INT nCount,struct lpHandles,INT bWaitAll,INT dwMilliseconds)");
 
var threadwait = function(bAll, ...){
    var threads = ...;
    if(type(threads)!=type.table)  
     threads ={...}
    
var threads_c = raw.toarray( threads ,"pointer" ,"array") 
var re = WaitForMultipleObjects(#threads,threads_c,bAll, 0xFFFFFFFF  /* Infinite timeout*/);
select(re) {
case 258 //WAIT_TIMEOUT 
return null,"超时" 
case 0xFFFFFFFF 
return null,"失败"  
}
return re+1;



thread.waitAll = function(...){
return threadwait(1,...);
}
thread.waitOne = function(...){
return threadwait(0,...);
}
thread.wait  = function(handle,ms=0xFFFFFFFF){
return WaitForSingleObject(handle,ms);
}



var SetThreadAffinityMask = Kernel32.api("SetThreadAffinityMask","INT( int hThread,INT dwProcessAffinityMask)" )
thread.setAffinity = function( h,cpu = 1){
    SetThreadAffinityMask( h,cpu );
}



thread.setAffinity(__,2) = 指定线程在哪个CPU上运行
thread.setAffinity(__) = 指定线程在CPU 1上运行 



例子:

io.open(); //io.open建议不要在子线程中调用
io.print("多线程演示程序")

f = 
function(arg){
    
import win; //线程函数内部要添加自已的import语句
    
    
    
for(i=1;10;1){
    
        io.print(
"线程ID:" + thread.getId()  );
        io.print(
"收到的参数:" + arg.str );
        
        thread.lock(
"临界区名称");
        
        
try//预防抛出异常时 thread.unlock 无法执行
        
            
//加锁范围内的代码能避免多线程重入
            var test  = thread.get("标志名称")
            test++;
            thread.set(
"标志名称", test); 
            io.print( thread.get(
"标志名称") );
        }
            
        thread.unlock(
"临界区名称")
        
        
sleep(1000)
    }

}

thread.set(
"标志名称", 1); //多线程需要通过此函数交换变量
hander,id = thread.create(f,{int=123;str="你好"} )
hander2,id2  = thread.create(f,{int=456;str=
"大家好"} )

io.print(
"thread.waitAll开始等待所有线程")
thread.waitAll(hander,hander2);
io.print(
"thread.waitAll函数返回")

例子:线程共享区CALL.aau

commonThreadFunc = function(a,b){
    io.print(
"参数",owner,a,b)
    io.print(
"线程变量",threadvar)
    
return 1,2,a + b
}
//将一个函数写入线程共享区(通常应当在主线程中一次性写入)
thread.set("threadfUNC", commonThreadFunc);
thread.set(
"threadvar", 123);

io.open()

//调用线程共享区函数,用法类似call函数
//第一个参数以字符串形式指定函数名字,第二个参数显式指定owner参数,后面可以是任意多个其他参数
io.print( thread.call("threadfUNC","owner",3,11) ) //在控制台输出所有返回值。



多线程之间发送接收消息的范例

import win;

//创建线程
th,tid = thread.create(

    
function(){
        
//线程代码
        import win;
        io.open()
        io.print(
"我是创建的线程,我在等待消息")
        
        msgproc  = 
function(msg){
            io.print(
"收到消息", msg.message )
        }
        
//启动消息循环,并注册观察者
        win.loopMessage(msgproc)
        
        io.print(
"线程退出")
    }
    
)


win.delay(1000)

//发送线程消息
::PostThreadMessage(tid,123,0,0);

//发送退出消息
::PostThreadMessage(tid,0x12/*_WM_QUIT*/,0,0)


这个实例很有趣。好像只有传int?要传str呢?
thread.set 是干什么的?
峰回路转,又回来了。




1.线程中怎么调用自定义函数



我定义了一个自定义函数,以及创建了一个线程,想在线程里调用 winform 代码中的自定义函数。不过线程好像跟 winform 不是一个 namespace,用 import winform 之类的也不行,不知道能否直接调用?
还是要自定义一个消息,用 SendMessage,然后窗口再去响应?

用 SendMessage 实现了,效果还不错

窗体是基于消息机制的,用消息是不错的方法,而且不需要考虑线程同步(消息可以在单线程中实现异步)。只要在创建线程的时候把窗体句柄传进去就可以了,反过来也可以给线程发消息,用  ::PostThreadMessage
线程之间用thread.get 、thread.set读写变量,会自动处理同步的问题。


阅读(3365) | 评论(2) | 转发(0) |
1

上一篇:怎么取网页数字

下一篇:win窗口库函数

给主人留下些什么吧!~~

chinaunix网友2011-02-22 03:45:11

https://my.wayi.com.tw/registry/registry.aspx

chinaunix网友2011-01-24 03:38:11

http://software.intel.com/zh-cn/blogs/2009/09/23/400002370/