aardio 官方社区

 找回密码
 注册会员

QQ登录

只需一步,快速开始

搜索
查看: 7950|回复: 2

跨线程操作窗口控件plus控件涉及gdip.bitmap的split()函数报错的问题

[复制链接]

4

主题

45

回帖

733

积分

三级会员

积分
733
发表于 2018-4-17 00:32:41 | 显示全部楼层 |阅读模式
先上代码:
  1. import win.ui;
  2. import gdip;
  3. /*DSG{{*/
  4. var winform = win.form(text="aardio form";right=759;bottom=469)
  5. winform.add(
  6. button={cls="button";text="button";left=227;top=328;right=456;bottom=401;z=2};
  7. plus={cls="plus";left=125;top=47;right=614;bottom=284;z=1}
  8. )
  9. /*}}*/

  10. //先在全局划分图片为数组,里面的bmp文件请自己根据实际情况设置一个
  11. gp=gdip.bitmap("\res\images\demo1.bmp").split(3,3,0,0,0,0);


  12. winform.button.oncommand = function(id,event){
  13.        
  14. //多线程调用,传递窗口对象和划分好的数组
  15. thread.invoke(
  16.         function(winform,gp){
  17.                 import win.ui;
  18.                 import gdip;
  19.                 for(i=1;9;1){
  20.                                 sleep(1000)
  21.                                 winform.plus.background=gp[i];
  22.                                 //本意是利用多线程实现界面的动画效果或者某种实时显示,这里用图片切片简单测试
  23.                                 //但是,在工作线程中调用会报错
  24.                 }
  25. },winform,gp
  26. )
  27. }

  28. winform.show()
  29. win.loopMessage();
复制代码


对多线程和gdi+了解不深,理解偏颇的地方请谅解。

看了几个多线程的例子,也看了软件自带的跨线程操作窗口控件,外加上前几天popdes提供了plus控件的例子,就有了这个想法,界面和动画(或者是数据实时处理显示)分离,避免界面反应卡顿,就想采用几个简单的函数做个实例出来,没想到不采用多线程正常执行,塞到多线程里后报错,请对多线程有深入研究的高手指正批评,给我等新手指明思路。

170

主题

2169

回帖

1万

积分

管理员

积分
13161
发表于 2018-4-17 00:52:37 | 显示全部楼层
建议你还是仔细看一下开始页的多线程入门教程(不是要批评你,而是里面有答案)
记住一个原则就行:任何对象都不能跨线程共享使用( gdip.bitmap 也一样
winform窗口对象是可以跨线程调用 - 这不等于gdip.bitmap 也可以。

另外,你这个思路也有问题,
线程间交互是有成本的,把gdip.bitmap 传到工作线程又传回来,这完全没有必要嘛。
这相当于在论坛发帖子,跑到机房把服务器抱回家,把帖子保存上去,又把服务器抱回机房。

所以,其实你并不需要这么做,代码可以更简单:
import win.ui;
/*DSG{{*/
var winform = win.form(text="aardio form")
winform.add(
button={cls=
"button";text="点里里观赏多线程动画";left=227;top=328;right=456;bottom=401;z=2};
plus={cls=
"plus";left=234;top=209;right=354;bottom=297;z=1}
)
/*}}*/

var gp=gdip.bitmap("~\extensions\wizard\project2\template\plus\2\res\Images\pl_pause.png").split(4);
winform.plus.setBackgrondIdx =
function(i){
    winform.plus.background = gp[ i ];
}

winform.button.oncommand =
function(){
        
    thread.invoke(
        
function(winform){  
            
for(i=1;4){
                winform.plus.setBackgrondIdx(i);
               
sleep(500)
            }
        },winform
    )
}

winform.show()
win.loopMessage();
import gdip不需要,因为plus控件会自动导入gdip.bitmap;
线程里不需要 import win.ui ,gp应当用var声明为局部变量。

4

主题

45

回帖

733

积分

三级会员

积分
733
 楼主| 发表于 2018-4-17 08:46:04 | 显示全部楼层
感谢Jacen的解答,认真地看了一遍起始页的 重写教程:多线程入门 http://bbs.aardio.com/forum.php?mod=viewthread&tid=13625&from=portal任何对象都不能跨线程共享使用 的原则我记住了,winform对象是特权对象,所以可以直接传递,但是不是所有的对象可以跨线程传递,尤其是涉及到文件、内存数据等,这会违反线程的安全原则,如果涉及到对窗体(或者主线程)的不可传递对象的操作,可以使用在主线程创建成员函数,利用winform间接调用成员函数的形式来操作,但应当尽量避免这样的骚操作,进程间最好是传递上下文无关的、不涉及局部变量的纯参数。

如果其他新手也有多线程/跨线程操作窗口控件、界面与逻辑分离、多线程涉及窗口控件调用报错的问题,请务必阅读 重写教程:多线程入门 http://bbs.aardio.com/forum.php?mod=viewthread&tid=13625&from=portal,不要像我一样把多线程问题想得简单,想当然地玩骚操作。
您需要登录后才可以回帖 登录 | 注册会员

本版积分规则

手机版|未经许可严禁引用或转载本站文章|aardio.com|aardio 官方社区 ( 皖ICP备09012014号 )

GMT+8, 2024-10-4 20:01 , Processed in 0.066855 second(s), 22 queries .

Powered by Discuz! X3.5

Copyright © 2001-2024 Tencent Cloud.

快速回复 返回顶部 返回列表