不暗啦,不黑啦...

yebie

 
 
 
 
 
 
 
 
 
 
下载音乐盒  曲目表歌词秀
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

  yebie

上海市 闵行区 处女座

 发消息  写留言

 
自我介绍继续扯乎
近期心愿还是胡扯
博客等级加载中...
今日访问加载中...
总访问量加载中...
最后登录加载中...
 
 
 
 
 
 
 
心情随笔列表加载中...
 
 
 
 
 
 
 
日志评论
 
 
 
 
 
 
 
 

[随手记录] UI 控件的 多线程访问

2009-10-30 13:57:35 阅读(7) 评论(0)


[问题]    话说我用C#写了个程序,带UI的,其中有个大框,专门用于记录程序运行的log,叫做logbox. 我加了一个这样的函数:
  public class XXX
  {...
    static public void Log(string p){ logbox.AppendText(p + "\r\n");}
  }
    这样,我就可以用 XXX.Log("I'm a pig");来实时记录log了。
    后来啊,工具改善了,实际运行的时候变成多线程了,加快速度嘛。这个时候,如果某个线程有 XXX.Log("abc"), 会抛出运行时错误,说logbox被另外的线程独占了,你这句代码执行不了。

[原因定位] 因为.NET的UI控件这东西,是专门有个线程管理的——或者说,谁创建了它就一直死皮赖脸的占用它。所以其它线程试图访问时就会抛错。

[解决思路]
1. 让创建线程把对UI控件的控制权统统交出来。
2. 让UI控件想办法不再只受一个线程的控制。
3. 其它线程告诉创建线程“老子要让UI做啥事”,创建线程再去帮忙做这些事。

[解决方法]
1.  如果是WinForm,那可以加一句
    Control.CheckForIllegalCrossThreadCalls = false;
    意思就是说,从其他线程来的对UI控件的请求不再被过滤并抛错,而是直接执行。这个简单,但是后果难以预计。不推荐。
2. 如果还是WinForm(可以看做.NET 很早就有的UI库),有一个号称灰常安全的方法,改造XXX::Log方法,采用委托:
   public class XXX
  {...
    private delegate void LogMethod(string p);
    static public void Log(string p){
      LogMethod m = new LogMethod(logbox.AppendText);
      logbox.Invoke(m, p+"\r\n");
    }
  }
    代码意思就是委托了logbox的创建线程去执行一次logbox.AppendText方法,并且参数是p + "\r\n".
3. 如果是WPF(.NET 3.0之后出现的一套新UI库),这正是我当前遇到的问题……我找了半天,没找到这个logbox有啥Invoke方法或是BeginInvoke方法。终于找了两个小时(当然其中吃了一顿乏味的中饭)之后找到了,原来WPF的空间要这么写:
    logbox.Dispatcher.Invoke(DispatcherPriority.Normal, m, p+"\r\n");
   WPF把这个Invoke从UI控件的直接方法里面移掉了,统一放在Dispatcher这个子对象里面,而且加上了一个优先级的参数。其它跟WinForm的一样。
4. 感谢某位做UI Automation的童鞋,给出了如下的万能解决方案(伪代码):
    mouse.instance.movepointto(logbox)
    mouse.instance.click()
    keyboard.instance.sendkeys("abc")
我只想说,你丫的真是太油菜了!我要自己写个log还好,要是我要输出Exception 的StackTrace,是不是应该去吃个饭再来啊?

阅读(7) | 评论(0) | 阅读全文>>

恩,巡视一把

2009-10-21 0:10:08 阅读(9) 评论(0)

    恩,评论和留言里面出现了一些陌生人。。。为啥更新这么低还有人踩呢?说明网易博客的博主连接功能做得好?

    另外,不看上周的快乐大本营,我还真不知道super junior出了M版!何炅学长还说观众把过道都坐满了,nc的九零后啊……

    恩,预报一下,本周五天天向上是windows7&微软专场,响应22号也就是周四的window7首发。就凭敢到天天向上开专场,这就值得看看。

   

阅读(9) | 评论(0) | 阅读全文>>

关于一个弱智问题的特殊情形讨论

2009-8-26 23:48:57 阅读(5) 评论(0)

弱智问题:假设有个单向的链表,不知道多长,现在我要知道倒数第n个元素的值,怎么办?假设对应类如下定义(java version):
  class Ele{
      public Ele next(){...}
      public int value(){...}
  }
  当前只给你一个链表头元素 headEle, 以及n。这里都假定链表暴长,而n是一个比较小的数字。
弱智问题回答:还在读书的童鞋们要记住了(工作过的或多或少都见过这个),标准通用最佳答案思路: 取一个临时指针(或者引用,whatever)叫做first,先让它从headEle开始走n步,然后再来个指针/引用 second,让second等于headEle;接下来first走一步再second走一步,保证一次循环下来first跟second都保持n个元素的距离;当first走到底了,second就是倒数第n个啦。这中间再注意些特殊情形例如链表长度确实比较短甚至短过n怎么办啊,循环链表怎么办啊,到底是保持距离n还是n-1啊之类的,保证让你的面试官觉得你一定背过这个题。

好,引申一下。这种答案有什么不太稳妥的地方?
这种方法的复杂度其实很好,空间复杂度是两个指针的额外内存;时间复杂度是链表长度(假设为m),等于是2*m -n,是链表长度的线性函数,灰常舒服。
问题在于,2*m-n步里,都是xxEle=xxEle.next()这样的操作。如果这个next()操作是个很耗费时间的操作,你会不会希望更进一步的压缩步骤?

引申出的弱智问题之特殊情形
  假设有个网上留言系统,人们只能1)发一个公开的新留言给别人; 2)公开回复别人的留言;3)公开回复别人的回复。那么,可能有人把它当做网上聊天系统,A给B留言,B回复给A,A又回复给B,然后C又回复了A给B的回复,然后A又回复了C的回复……这样就会有个让人头大的回复系统。
  继续假设,这个系统的设计者为了简单,数据库中间没有区分留言和回复,都放在一个叫做Message的表里头,只是所有回复的replyTo字段会填入被回复的那条记录的id,但是新留言的这个字段为0. 例如A给B的新留言,id为100,replyTo为0;那么B如果有对应的回复,回复的id为101,replyTo为100.
  好,这一步步陷阱都设计好了,有一天,策划将程序推下了深渊:我现在给定一个不知道到第多少次了的回复,想要知道其对应的最开始的新留言以及头两次回复。
特殊情形之特殊解决:
  其实,这个需求可以归结为“寻找链表中的倒数第三个元素”的问题,也就是第二次回复记录。但是,这里的next()相当恐怖,因为是个DB的query(假定DB的query真的很恐怖。。。)。如果那个回复的水很深,例如第20层,那就需要38次查询才能定位,再要2次查询获取第一次回复和新留言的内容。
改进的解决方案:
  目标很简单:减少next()次数,尽可能争取每个记录只要查询一次搞定。
  思路:不再是时刻保持first跟second的距离一直为n的策略,而是先将first跟second相等,每次循环中,first先往前探测n步,如果没到结尾,second就跳过中间的那些一步步挪的过程,直接再次跟first相等,然后再循环;到了最后,first到底了,second肯定到first的距离小于n,那么在second之后还要留一个third指针,记录second刚刚挪开的位置;最后,从third开始到结尾的这个小列表中(长度大于n小于2n),寻找倒数第n个就容易多了。
  伪代码如下:
  Ele firstEle=secondEle=thirdEle=headEle;
  int i=n, j=n;
  while(firstEle!=null && i >0)
  { firstEle=firstEle.next(); i--;}
  if (firstEle == null){/*链表长度小于n的处理/*}
  while(firstEle != null)
  {thirdEle = secondEle, secondEle = firstEle;
    j=n;
    while(firstEle!=null && j>0)
    { firstEle=firstEle.next(); j--;}
    if (firstEle==null) break;
  }
  //刚好first跟second距离是n。。。直接返回second
  if (j==0) return secondEle;
 //first最后一次while里挪动了 n-j步,那么比second领先了n-j步,那么比third领先2n-j步,那么third也应该往前挪动n-j步,就是所求的倒数第n个
  if(j>0)
  { while(j<n){j++; thirdEle = thirdEle.next();} return thirdEle;}

代码done。可以看到,最多调用了next()步骤m+n次。虽然有大概2*m/n次的xxEle = yyEle这样的操作,但对于这个例子来说,这等于是指针可以用回复的id来代替,这样的赋值就变成了int或者long型的赋值而已,而空间复杂度也不高,三个临时指针加两个临时int(两个int还可以合并)。

欢迎批评指正~

阅读(5) | 评论(0) | 阅读全文>>

终于搞定了flash player的问题

2009-8-26 16:29:20 阅读(200) 评论(3)

现象:
     用ie打开一个含flash的网页,出现至少十几分钟的电脑极度缓慢的状态。硬盘灯一直亮不会灭,任何操作都慢得出奇,尤其是需要读写硬盘的操作——在已用内存超过物理内存的时候,简直是慢得发指。
    firefox下一切正常。

环境:
    OS:windows 7 RC en ultimate
    browser: ie8
    flash player: 10.0.32.18
    其它可能相关软件:小红伞杀毒软件+360安全卫士

分析:
    打开任务管理器,可以看到当用ie打开一个含flash的网页时,多了一个flashUtil10c.exe的运行。查看IO read和 IO write的数据,这个进程其实并不多IO操作。反倒是一个crcss.exe(好像系统自己的)和一个wltray.exe(无线网卡相关的)比较频繁,但是也不觉得是很恐怖的那种。
    再打开performance monitor,查看 disk write bytes/sec和disk read bytes/sec, 可以看到write操作比read操作多很多。基本可以保证是因为频繁写硬盘操作导致系统缓慢。但是还是无法知道怎么回事。

解决过程:
     因为flash player的更新是通过360安全卫士的软件升级功能进行的,所以首先查看flash player对应论坛,发现近期有不少人报不爽但是都没有软件测试的经验,sigh……除了坚定信心不是我自己的问题,没其它用处。
     然后昨天实在受不了了,上baidu查,一如既往的不知所云。到google搜了一下,发现国外脑残也不少。
    然后今天开始读adobe官网论坛,差点要疯了。照样是很多过于模糊的描述,不过比外面好不少。
    终于……让我找到了:http://forums.adobe.com/message/2151836#2151836。copy 如下:
    One of my users have reported about strange issue with Flash Player 10.0.32.18l. With IE8 under Vista/W7 he discovered unclosed FlashUtil10c.exe process instances. After my investigation, it became absolutely clear that the issue is caused by the Adobe programmers who forgot to decrease references for the internal COM objects of the FlashUtil10c.exe process. Hope, you will fix the issue up soon. If you need an additional information- feel free to contact me.
    ...
    Adobe correction is needed.

正准备放弃的时候,看到一个个人博客,真够牛叉的,flash player每出一个版本,他老人家就发一篇文章告诉大家怎么解决常见flash player不工作的问题!而且是绝对傻瓜型!
发现了一招:http://thetechangel.com/blogberry/2009/08/flash-10c-fix/
然后,it really works for me!

正式解决方案:
0.为了保险,我们还是先清除本机版本的flash并安装最新版本吧。
   a) 官方删除工具先下载,记住是下载,不要直接运行
   b) 把能关的软件都关了,包括各种浏览器,聊天工具,下载工具视频工具等等,谁知道它们会不会自己访问一个flash。最好右下角的图标也扫一边,确认一次。
   c) 刚才下载的软件,运行。运行完要是觉得太快,你可以没事多运行几次。然后重启,不仅仅是重新登录啊。
   d) 启动,开个ie访问有flash的网站试试,应该不显示出来吧。然后去官方下载网站,重新下载一次。
   e) 还没到结束的时候。关掉ie吧,暂时别动。

1. 找到flash安装目录。 通常在 C: 盘 > Windows > System32 > Macromed > Flash里面。
2. 找到一个叫做flashUtil10c.exe的文件。右键猛击它,菜单中选择“Run as Administrator",中文请自行揣摩。
3. 然后开始了吭哧吭哧的下载,可能会有提示让你确认,确认就是。国内的童鞋可能要稍微久一点,因为adobe官方下载相当慢。
4. 好了……

阅读(200) | 评论(3) | 阅读全文>>

查看所有日志>>

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2009