找回密码
 注册
搜索
查看: 989|回复: 0

[综合资料] 再议j2me进度条与线程化模型

[复制链接]
发表于 2005-12-22 23:08:00 | 显示全部楼层 |阅读模式
<TABLE cellSpacing=10 cellPadding=0 width="100%" border=0>

<TR>
<TD class=fontbig vAlign=top>
<P ><p><FONT face="Courier New"> </FONT></p></P>
<H2 ><FONT size=3>前台UI如何和后台线程交互</FONT></H2>
<P ><FONT face="Courier New">原文中模型,是一个前台的ProgressGaugeUI与后台线程无关的模型。这样设计的时候最大程度上的化简了通信的复杂性,实际上是一种单方向的模型(由BackgroundTask 向 PGUI通信)。按照这种模式的要求,程序员在Override BackgroundTask 的runTask()方法时,有义务定期的去查训前台的PGUI的运行情况,并根据这种情况做出反映。这样这种模式完全相信后台线程,将是否响应用户cancel命令的权利交给了后台线程,如果后台线程陷入麻烦没有响应了(比如访问一个很昂贵的网络连接),此时用户试图cancel也没有用,程序将会暂时的死锁,直到后台线程有时间去检查前台的状态。并且在实际情况中,到底什么时候去查询,多大的频率都是问题。在代码段中过多的此类代码,会影响对正常的流程的理解。</FONT></P>
<P ><p><FONT face="Courier New"> </FONT></p></P>
<P ><FONT face="Courier New">从下面的这个顺序图,可以看到这个具体流程:</FONT></P>
<P ><v:shapetype><v:stroke joinstyle="miter"></v:stroke><v:formulas><v:f eqn="if lineDrawn pixelLineWidth 0"></v:f><v:f eqn="sum @0 1 0"></v:f><v:f eqn="sum 0 0 @1"></v:f><v:f eqn="prod @2 1 2"></v:f><v:f eqn="prod @3 21600 pixelWidth"></v:f><v:f eqn="prod @3 21600 pixelHeight"></v:f><v:f eqn="sum @0 0 1"></v:f><v:f eqn="prod @6 1 2"></v:f><v:f eqn="prod @7 21600 pixelWidth"></v:f><v:f eqn="sum @8 21600 0"></v:f><v:f eqn="prod @7 21600 pixelHeight"></v:f><v:f eqn="sum @10 21600 0"></v:f></v:formulas><v:path extrusionok="f" gradientshapeok="t" connecttype="rect"></v:path><lock v:ext="edit" aspectratio="t"></lock></v:shapetype></P>
<P ><p><FONT face="Courier New">
<TABLE cellSpacing=1 cellPadding=0 align=center bgColor=#cccccc border=0>

<TR>
<TD>
<TABLE cellSpacing=0 cellPadding=0 bgColor=#ffffff border=0>

<TR>
<TD><IMG src="http://www.52rd.com/upload/2005_12/images20051222234681961.jpg" border=0></TD></TR></TABLE></TD></TR></TABLE> </FONT></p></P>
<P ><FONT face="Courier New">我们需要一个方法,让我们能够强制的结束Task。这个方法由背景线程自己提供,取名叫做cancel()。当然没有任何一个方法可以强迫线程立即结束(曾经有,因为安全性问题而被取消)。所以cancel()方法往往通过关闭的资源(一个连接,一个流等)来迫使runTask发生异常被中断,runTask有义务根据自己的约定捕捉此类异常并立即退出。一图胜千言,让我们看看这种方法的流程。</FONT></P>
<P ></P>
<P ><p><FONT face="Courier New"> <FONT face="Courier New">
<TABLE cellSpacing=1 cellPadding=0 align=center bgColor=#cccccc border=0>

<TR>
<TD>
<TABLE cellSpacing=0 cellPadding=0 bgColor=#ffffff border=0>

<TR>
<TD><IMG src="http://www.52rd.com/upload/2005_12/images200512222342885232.jpg" border=0></TD></TR></TABLE></TD></TR></TABLE></FONT></FONT></p></P>
<P ><FONT face="Courier New">很显然的,关键在于前台的线程对后台的线程进行了回调,这样就可以解决问题了。但是新的问题来了,这样做迫使我们将前台与后台线程紧密的耦合在了一起(因为要回调嘛)。能不能既实现回调又避免前台UI与后台线程的紧密耦合呢?</FONT></P>
<P ><p><FONT face="Courier New"> </FONT></p></P>
<H2 ><FONT size=3>通过Cancelable接口降低耦合度</FONT></H2>
<P ><FONT face="Courier New">幸好,我门可以利用接口来实现这一点。</FONT></P>
<P ><FONT face="Courier New">先前的模型是这样的:</FONT></P>
<P ><FONT face="Courier New">
<TABLE cellSpacing=1 cellPadding=0 align=center bgColor=#cccccc border=0>

<TR>
<TD>
<TABLE cellSpacing=0 cellPadding=0 bgColor=#ffffff border=0>

<TR>
<TD><IMG src="http://www.52rd.com/upload/2005_12/images200512222343979898.jpg" border=0></TD></TR></TABLE></TD></TR></TABLE></FONT></P>
<P ></P>
<P ><FONT face="Courier New">为了降低耦合,我们建立一个接口</FONT></P>
<P ><FONT face="Courier New">public interface Cancelable {</FONT></P>
<P ><FONT face="Courier New">    /**</FONT></P>
<P ><FONT face="Courier New">     * 本方法非阻塞,应该立即返回(如有必要开启新的线程)</FONT></P>
<P ><FONT face="Courier New">     * 此外应避免对此方法的重复调用</FONT></P>
<P ><FONT face="Courier New">     */</FONT></P>
<P ><FONT face="Courier New">    public void cancel();</FONT></P>
<P ><FONT face="Courier New">}</FONT></P>
<P ><FONT face="Courier New">接下来在ProgressObserver加入对这个方法的支持</FONT></P>
<P ><FONT face="Courier New">public interface ProgressObserver {</FONT></P>
<P ><FONT face="Courier New">    ……</FONT></P>
<P ><FONT face="Courier New">    ……</FONT></P>
<P ><FONT face="Courier New">    /**</FONT></P>
<P ><FONT face="Courier New">     * 设置取消Task时回调的函数对象</FONT></P>
<P ><FONT face="Courier New">     * @param co</FONT></P>
<P ><FONT face="Courier New">     */</FONT></P>
<P ><FONT face="Courier New">    public void setCancelalbeObject(Cancelable co);</FONT></P>
<P ><FONT face="Courier New">}</FONT></P>
<P ><p><FONT face="Courier New"> </FONT></p></P>
<P ><FONT face="Courier New">这样,就可以在用户按下取消按钮的时候,就可以进行对Cancelable.cancel()的回调。这样灵活性大大增强了。</FONT></P>
<P ></P>
<P ><p><FONT face="Courier New">
<TABLE cellSpacing=1 cellPadding=0 align=center bgColor=#cccccc border=0>

<TR>
<TD>
<TABLE cellSpacing=0 cellPadding=0 bgColor=#ffffff border=0>

<TR>
<TD><IMG src="http://www.52rd.com/upload/2005_12/images200512222345252790.jpg" border=0></TD></TR></TABLE></TD></TR></TABLE> </FONT></p></P>
<H2 ><FONT size=3>新代码</FONT></H2>
<P ><FONT face="Courier New">    更新后的代码如下,除了改用以上的模型外,还对部分的BUG进行了更正,更改的地方会用不同的颜色表示。详细的用法可参见注释</FONT></P>
<P ><p><FONT face="Courier New">
<a href="http://www.j2medev.com/Article/UploadFiles/200532203154310.rar" target="_blank" ><FONT color=#000000>点击浏览该文件</FONT></A></FONT></p></P></TD></TR>
<TR>
<TD>
<SCRIPT type=text/javascript><!--
google_ad_client = "pub-3720468914994936";
google_ad_width = 468;
google_ad_height = 60;
google_ad_format = "468x60_as";
google_ad_type = "text";
google_ad_channel ="";
google_color_border = "FFFFFF";
google_color_bg = "FFFFFF";
google_color_link = "0000FF";
google_color_url = "666666";
google_color_text = "000000";
//--></SCRIPT>

<SCRIPT src="http://pagead2.googlesyndication.com/pagead/show_ads.js" type=text/javascript>
</SCRIPT>
<img height="1" width="1" border="0" src="http://pagead2.googlesyndication.com/pagead/imp.gif?event=noiframe&client=ca-pub-3720468914994936&dt=1135263975890&lmt=1135263969&prev_fmts=300x250_as&format=468x60_as&output=html&url=http%3A%2F%2Fwww.52rd.com%2FS_Txt%2F2005_12%2FTxt3015.htm&color_bg=FFFFFF&color_text=000000&color_link=0000FF&color_url=666666&color_border=FFFFFF&ad_type=text&ref=http%3A%2F%2Fwww.52rd.com%2Fadmin%255Fadmin%2Ftxt_manage.asp&cc=820&u_h=1024&u_w=1280&u_ah=994&u_aw=1280&u_cd=32&u_tz=480&u_java=true" /></TD></TR></TABLE>
高级模式
B Color Image Link Quote Code Smilies

本版积分规则

Archiver|手机版|小黑屋|52RD我爱研发网 ( 沪ICP备2022007804号-2 )

GMT+8, 2024-11-26 20:17 , Processed in 0.057137 second(s), 16 queries , Gzip On.

Powered by Discuz! X3.5

© 2001-2023 Discuz! Team.

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