<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title></title>
	<atom:link href="http://www.zzgan.com/?feed=rss2" rel="self" type="application/rss+xml" />
	<link>http://www.zzgan.com</link>
	<description>跬步至千里　小流成江海</description>
	<lastBuildDate>Wed, 01 Sep 2010 16:29:42 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>人说懒到家了，我更甚，懒到床上去了</title>
		<link>http://www.zzgan.com/?p=146</link>
		<comments>http://www.zzgan.com/?p=146#comments</comments>
		<pubDate>Wed, 01 Sep 2010 16:29:42 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[冇分类]]></category>

		<guid isPermaLink="false">http://www.zzgan.com/?p=146</guid>
		<description><![CDATA[从淘宝拍的懒人桌今天收到了，很适合我啊，可以平躺下玩电脑了，从官网下了张图，show 一下。
爽，我喜欢
]]></description>
			<content:encoded><![CDATA[<p>从淘宝拍的懒人桌今天收到了，很适合我啊，可以平躺下玩电脑了，从官网下了张图，show 一下。<a href="http://www.zzgan.com/wp-content/uploads/2010/09/T2RmRhXnNXXXXXXXXX_87483582.jpg"><img class="aligncenter size-medium wp-image-147" title="T2RmRhXnNXXXXXXXXX_!!87483582" src="http://www.zzgan.com/wp-content/uploads/2010/09/T2RmRhXnNXXXXXXXXX_87483582-225x300.jpg" alt="" width="225" height="300" /></a></p>
<p>爽，我喜欢</p>
]]></content:encoded>
			<wfw:commentRss>http://www.zzgan.com/?feed=rss2&amp;p=146</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>碰了碰 云</title>
		<link>http://www.zzgan.com/?p=144</link>
		<comments>http://www.zzgan.com/?p=144#comments</comments>
		<pubDate>Mon, 30 Aug 2010 17:40:02 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[冇分类]]></category>

		<guid isPermaLink="false">http://www.zzgan.com/?p=144</guid>
		<description><![CDATA[云，早已不是一个什么新鲜东东了，看来我还是真的后知后觉，老是慢上那么几步。...... 这让我想起了阿凡达，也许某一天真的是那，人只是作也一个“端”，可以接到地球这个主机上。]]></description>
			<content:encoded><![CDATA[<p>云，早已不是一个什么新鲜东东了，看来我还是真的后知后觉，老是慢上那么几步。</p>
<p>网上转了一圈，也没有对云计算有个清楚的定义，感觉就象“哲学”一样赖皮，说所有的知识都是哲学的范筹。<a href="http://baike.baidu.com/view/1316082.htm?fr=ala0_1">http://baike.baidu.com/view/1316082.htm?fr=ala0_1</a> 这是百度百科的解析，反是我是没怎么看懂，（能为有限），就我个人现在的理解，所谓云，就是计算机从单一的点向网络化发展。想想也是这么个趋势，我对什么发展史之类的比较文盲，也不知道网络发展的什么什么几个阶段，只是觉得好象是这个么方向，从“单机游戏”到“网上冲浪”到“网络游戏”，网吧打出来的标语也是这个发展过来的。可能是先入为主的应因，也或是从单机到可以上网使我过于兴奋，让我对“网络”的认识停留在“网站”这个位置上，新间网站、社区网站、BBS、BLOG、电子商务 &#8230; &#8230; ,感觉“网络”给于我的已经够的了。然而，技术永远是发展的，在人们不停膨胀的需求中，使一批我这个后知后觉的人反应不过来（也需这类人只有我一个哦 ）。</p>
<p>      总结来说，我的认识云就网络版的应用服务程序（仅个人看法）。这让我想起了阿凡达，也许某一天真的是那，人只是作也一个“端”，可以接到地球这个主机上。</p>
<p>      先不管什么是云的定义了，对于程序员来说，一个helloworld是再有说服边不过了。网上说 <a href="http://appengine.google.com">Google App Engine </a>算是 云的一个例子，就注册了一个。<a href="http://opmetic.appspot.com/">helloworld</a>是出来了，但好象还没尝到云是啥味道。也不管是啥味道了，至少我有一个理由就学习新东西——python了</p>
]]></content:encoded>
			<wfw:commentRss>http://www.zzgan.com/?feed=rss2&amp;p=144</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>又是一个结束的故事</title>
		<link>http://www.zzgan.com/?p=142</link>
		<comments>http://www.zzgan.com/?p=142#comments</comments>
		<pubDate>Sun, 29 Aug 2010 13:53:15 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[冇分类]]></category>

		<guid isPermaLink="false">http://www.zzgan.com/?p=142</guid>
		<description><![CDATA[玩玩仙剑4]]></description>
			<content:encoded><![CDATA[<p>几天的努力，把仙剑4通关了。回味几个过关动画，早已不相信仙剑中唯美的童话爱情的我，还是被小小感动了。虽然两年前就有很多玩家对仙剑4的感慨，我已算是翻出陈谷子烂麻了。</p>
<p>        不论怎么说，4的结局最美好的，一百年的跨跃，给我们留下太多想象的空间。网上也搜到各家对结局的说法，但游戏中每个主人翁都得到了最好结局还是让人感到欣慰。天河因被龙大哥给阎王开的一个玩笑，有了不死之身，韩MM，网友们都说她是最幸福了，以短短的生命中能和最爱的人在一起，可我觉得，为什么不能把这个幸福扩大一点呢？韩MM没有应命早逝，而是与天河白头到老了（当然只有她一个人白头了）。修仙的也修得了正果，一百年都不死，估计是修成仙身了。柳MM，虽为妖身，却是我最喜欢的型了(为什么我碰不到呢)，经过一百年的个人事业发展，也可以隐退了，来到人间，和天河长相私守了。</p>
<p>      感慨过后，久久不能回到现实中来，也许，那个向往童话的心又在作怪了。现在的生活，没有仙，也没有妖，没有天河的单纯，也没有柳MM的清纯，有的就是无限放大的人的欲望。</p>
<p>      欲求仙道，先求人道，也许这是这个游戏给我最现实的收获。虽然现实有太多的我不认同，但依然要坚持作为凡人的人道。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.zzgan.com/?feed=rss2&amp;p=142</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>windows 7 下加grub for dos启动项</title>
		<link>http://www.zzgan.com/?p=140</link>
		<comments>http://www.zzgan.com/?p=140#comments</comments>
		<pubDate>Thu, 19 Aug 2010 16:35:09 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[windows]]></category>

		<guid isPermaLink="false">http://www.zzgan.com/?p=140</guid>
		<description><![CDATA[1：先去下载grub4dos
2：解压grldr.mbr,grldr,menu.lst三个文件到C盘根目录，注意是根目录哦！
3：然后以管理员模式运行cmd，输入bcdedit /create /d &#8220;grub&#8221; /application bootsector
会有一大串id，要记下，等下要用，然后：
4：bcdedit /set {id} device partition=c:
5：bcdedit /set {id} path \grldr.mbr
6：bcdedit /displayorder {id} /addlast
]]></description>
			<content:encoded><![CDATA[<p>1：先去下载grub4dos<br />
2：解压grldr.mbr,grldr,menu.lst三个文件到C盘根目录，注意是根目录哦！<br />
3：然后以管理员模式运行cmd，输入bcdedit /create /d &#8220;grub&#8221; /application bootsector<br />
会有一大串id，要记下，等下要用，然后：<br />
4：bcdedit /set {id} device partition=c:<br />
5：bcdedit /set {id} path \grldr.mbr<br />
6：bcdedit /displayorder {id} /addlast</p>
]]></content:encoded>
			<wfw:commentRss>http://www.zzgan.com/?feed=rss2&amp;p=140</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>php soap 开发文档</title>
		<link>http://www.zzgan.com/?p=110</link>
		<comments>http://www.zzgan.com/?p=110#comments</comments>
		<pubDate>Wed, 18 Aug 2010 15:13:33 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[soap]]></category>
		<category><![CDATA[技术]]></category>
		<category><![CDATA[php]]></category>

		<guid isPermaLink="false">http://www.zzgan.com/?p=110</guid>
		<description><![CDATA[php soap 开发文档 一． 必备知识 1.wsdl(web服务标记语言) WSDL（网络服务描述语言，Web Services Description Language）是一门基于 XML 的语言，用于描述 Web Services 以及如何对它们进行访问。 具体参考请访问下面网址 http://www.w3school.com.cn/wsdl/index.asp 2.soap SOAP 是一种简单的基于 XML 的协议，它使应用程序通过 HTTP 来交换信息。 具体参考请访问下面网址 http://www.w3school.com.cn/soap/index.asp 3.php扩展 具体参考请访问下面网址 http://php.net/manual/en/book.soap.php 二． php soap开发模式 1. working in swdl mode(契约先行(Contract first)模式) 　　契约先行模式使用了一个用XML定义的服务接口的WSDL文件。WSDL文件定义了服务必须实现或客户端必须使用的接口。SoapServer和SoapClient的WSDL模式就基于这个概念。也就是用soap通讯的时候必须先有一个定义过的服务接口，才能进行通讯。 　　 2. working in non-swdl mode(代码先行(Code first)模式) 在代码先行模式中，首先要先写出实现服务的代码。然后在大多数情况下，代码会产生一个契约，换种说法，一个WSDL。接着客户端在使用服务的时候就可以使用那个WSDL来获得服务的接口。尽管如此，PHP5的扩展并没有从代码输出一个WSDL的规定，考虑到这种情况，可以在non-WSDL模式下使用 SoapServer和SoapClient。也就是说在soap通讯的时候并不需要一个预先定义过的服务接口，代码会自动的产生。 三．参考例子： 　　下面介绍如何使用WSDL模式和non-WSDL模式来实现服务和客户端。相对而言，使用WSDL模式来实现服务和客户端会比较容易。 1. noWSDL模式实现 服务端 server.php
&#8220;http://test-uri/&#8221;)); $server-&#62;setClass(&#8216;test&#8217;); [...]]]></description>
			<content:encoded><![CDATA[<p>php soap 开发文档 一． 必备知识 1.wsdl(web服务标记语言) WSDL（网络服务描述语言，Web Services Description Language）是一门基于 XML 的语言，用于描述 Web Services 以及如何对它们进行访问。 具体参考请访问下面网址 http://www.w3school.com.cn/wsdl/index.asp 2.soap SOAP 是一种简单的基于 XML 的协议，它使应用程序通过 HTTP 来交换信息。 具体参考请访问下面网址 http://www.w3school.com.cn/soap/index.asp 3.php扩展 具体参考请访问下面网址 http://php.net/manual/en/book.soap.php 二． php soap开发模式 1. working in swdl mode(契约先行(Contract first)模式) 　　契约先行模式使用了一个用XML定义的服务接口的WSDL文件。WSDL文件定义了服务必须实现或客户端必须使用的接口。SoapServer和SoapClient的WSDL模式就基于这个概念。也就是用soap通讯的时候必须先有一个定义过的服务接口，才能进行通讯。 　　 2. working in non-swdl mode(代码先行(Code first)模式) 在代码先行模式中，首先要先写出实现服务的代码。然后在大多数情况下，代码会产生一个契约，换种说法，一个WSDL。接着客户端在使用服务的时候就可以使用那个WSDL来获得服务的接口。尽管如此，PHP5的扩展并没有从代码输出一个WSDL的规定，考虑到这种情况，可以在non-WSDL模式下使用 SoapServer和SoapClient。也就是说在soap通讯的时候并不需要一个预先定义过的服务接口，代码会自动的产生。 三．参考例子： 　　下面介绍如何使用WSDL模式和non-WSDL模式来实现服务和客户端。相对而言，使用WSDL模式来实现服务和客户端会比较容易。 1. noWSDL模式实现 服务端 server.php</p>
<p><!--p  class test  {        /**         *         * @return string         */        function show()        {             return 'hello world!';        }  }  #####################################################  $server = new SoapServer(null, array('uri'-->&#8220;http://test-uri/&#8221;)); $server-&gt;setClass(&#8216;test&#8217;); $server-&gt;handle(); ?&gt; 客户端 client.php</p>
<p><!-- $soap=new SoapClient(null, array(  'location'-->&#8216;http://soapserver_url/server.php&#8217;, &#8216;uri&#8217; =&gt; &#8220;http://test-uri/&#8221;)); print_r($soap-&gt;__getFunctions()); echo $soap-&gt;show(); ?&gt; 2. WSDL模式实现 第一步：编写服务端类文件 class..php</p>
<p><!--p  class test  {        /**         *         * @return string         */        function show()        {             return 'hello world!';        }  }  -->第二步：将类文件生成 wsdl文件server.wsdl。 由于wsdl文件编写比较复杂，所以我们用第三方工具生成。我们以zend studio为例子演示： Tools ==&gt; WSDL Generator ==&gt; Configration name : test; WSDL file name: server ==&gt;ＮＥＸＴ　==&gt; 点击 + ==&gt; 选择上面的创建的class.php ==&gt; 这时候会看到一个 classes?? : URL Location的映射,保留 test类前面的勾，并将其url 设置为 SOAP Server的url：http://soapserver_url/server.php ==&gt;点击Finish，ZDE就会创建一个非常漂亮的WSDL了?? 工作基本上完成了. 第三步：服务端编写:</p>
<p><!--p  require ' class..php ';  //引入类文件     $server = new SoapServer('server.wsdl');  $serve-->setClass(&#8216;test&#8217;); $server-&gt;handle(); ?&gt; 第四步：客户端编写 $soap = new SoapClient(&#8216;http:// soapserver_url/server.wsdl&#8217;); print_r($soap-&gt;__getFunctions()); echo $soap-&gt;show(); 以上两个例子只是一个简单的soap服务编写，已经可以满足大部分需要。如果需要更加高级的功能请参考其他方面的资料。 三． 出现的问题。 1.在方法中对属性的赋值在其他方法中不起作用。 比如在客户端调用服务端某个方法对某个属性赋值。 在其他方法里就不能用。但在 __construct 方法中对属性的赋值是可以个在其他方法中使用的。 2. 提示 Client] looks like we got no XML document错误。 服务器端文件在</p>
<p><!--p-->标签前后都不要有任何数据包括空格，空行。 3. Warning: SoapClient::SoapClient(): I/O warning : failed to load external entity 原因如下：PHP程序作为 SOAP客户端 采用 WSDL 模式访问远端服务器的时候，PHP是通过调用 libcurl 实现的。至少在 PHP5.2.X 是这样的。如果采用 non-WSDL 模式，就不需要 libcurl。在solaris 没有缺省安装 libcurl，也许是我没有安装。除了 了ibcurl以外，至少还关联的库包括： libidn,ibgcc,libiconv,libintl,openssl 本文来自: PQ秀秀网(http://www.pqshow.com) 详细出处参考：http://www.pqshow.com/design/jiqiao/200910/12038.html</p>
]]></content:encoded>
			<wfw:commentRss>http://www.zzgan.com/?feed=rss2&amp;p=110</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>MFC 中作用 #index string 问题</title>
		<link>http://www.zzgan.com/?p=123</link>
		<comments>http://www.zzgan.com/?p=123#comments</comments>
		<pubDate>Fri, 13 Aug 2010 03:28:32 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[MFC]]></category>

		<guid isPermaLink="false">http://www.zzgan.com/?p=123</guid>
		<description><![CDATA[今天在MFC中，想使用#index ,结果是一大堆的xdebug、xlocale错误，网上找了一下，大致原因是在debug版下，new被重载（标准库stl内部对new进行了重载，两者互相冲突），在MFC的头文件中有以下代码：
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
解决方法很简单，把#include &#60;string&#62; 放在这个定义之前都OK了
]]></description>
			<content:encoded><![CDATA[<p>今天在MFC中，想使用#index ,结果是一大堆的xdebug、xlocale错误，网上找了一下，大致原因是在debug版下，new被重载（标准库stl内部对new进行了重载，两者互相冲突），在MFC的头文件中有以下代码：</p>
<blockquote><p>#ifdef _DEBUG<br />
#define new DEBUG_NEW<br />
#endif</p></blockquote>
<p>解决方法很简单，把#include &lt;string&gt; 放在这个定义之前都OK了</p>
]]></content:encoded>
			<wfw:commentRss>http://www.zzgan.com/?feed=rss2&amp;p=123</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>做个标记</title>
		<link>http://www.zzgan.com/?p=120</link>
		<comments>http://www.zzgan.com/?p=120#comments</comments>
		<pubDate>Wed, 04 Aug 2010 04:54:02 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[冇分类]]></category>

		<guid isPermaLink="false">http://www.zzgan.com/?p=120</guid>
		<description><![CDATA[突然意识到，不能在这样下去了，一天天的长胖，一天天的虚弱下去，长此以往，将偏离肮线越来越远。重拾斗志，加油。
hello world
]]></description>
			<content:encoded><![CDATA[<p>突然意识到，不能在这样下去了，一天天的长胖，一天天的虚弱下去，长此以往，将偏离肮线越来越远。重拾斗志，加油。<br />
<code>hello world</code></p>
]]></content:encoded>
			<wfw:commentRss>http://www.zzgan.com/?feed=rss2&amp;p=120</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>_beginthreadex和CreateThread</title>
		<link>http://www.zzgan.com/?p=118</link>
		<comments>http://www.zzgan.com/?p=118#comments</comments>
		<pubDate>Wed, 07 Jul 2010 16:59:16 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[windows]]></category>

		<guid isPermaLink="false">http://www.zzgan.com/?p=118</guid>
		<description><![CDATA[
[转：http://blog.chinaunix.net/u2/61062/showart_2065921.html]
为什么要用C运行时库的_beginthreadex代替操作系统的CreateThread来创建线程？

来源自自1999年7月MSJ杂志的《Win32 Q&#38;A》栏目
   你也许会说我一直用CreateThread来创建线程，一直都工作得好好的，为什么要用_beginthreadex来代替CreateThread，下面让我来告诉你为什么。
   回答一个问题可以有两种方式，一种是简单的，一种是复杂的。
如果你不愿意看下面的长篇大论，那我可以告诉你简单的答案：_beginthreadex在内部调用了CreateThread，在调用之前_beginthreadex做了很多的工作，从而使得它比CreateThread更安全。
    为什么我们需要两个几乎相同的库来分别对待单线程和多线程程序？说起来也很简单，两个字——效率。让我们从头说起，标准CRT库出现于1970年左右，那时，线程的概念尚未出现在任何一个操作系统上。但是，线程毕竟是出现了，那好，让我们来看看下面这个例子，在这个例子中我们使用了CRT的全局变量 errno：
BOOL fFailure = (system(&#8220;NOTEPAD.EXE README.TXT&#8221;) == -1);
if (fFailure) {
     switch (errno) {
     case E2BIG: // Argument list or environment too big
         break;
   case ENOENT: // Command interpreter cannot be found
       break;
   case ENOEXEC: // Command interpreter has bad format
       break;
   case ENOMEM: // Insufficient memory to run command
       break;
   }
} [...]]]></description>
			<content:encoded><![CDATA[<div>
<h2><span style="color: #0000ff; font-size: medium;">[转：<a href="http://blog.chinaunix.net/u2/61062/showart_2065921.html">http://blog.chinaunix.net/u2/61062/showart_2065921.html</a>]</span></h2>
<h2><span style="color: #0000ff; font-size: medium;">为什么要用C运行时库的_beginthreadex代替操作系统的CreateThread来创建线程？</span></h2>
<div>
<p><strong><span style="font-size: medium;">来源自自1999年7月MSJ杂志的《Win32 Q&amp;A》栏目</span></strong></p>
<p><span style="font-size: medium;">   你也许会说我一直用CreateThread来创建线程，一直都工作得好好的，为什么要用_beginthreadex来代替CreateThread，下面让我来告诉你为什么。<br />
   回答一个问题可以有两种方式，一种是简单的，一种是复杂的。<br />
如果你不愿意看下面的长篇大论，那我可以告诉你简单的答案：<span style="color: #ff0000;"><strong>_beginthreadex在内部调用了CreateThread，在调用之前_beginthreadex做了很多的工作，从而使得它比CreateThread更安全。</strong></span></span></p>
<p><span style="font-size: medium;">    为什么我们需要两个几乎相同的库来分别对待单线程和多线程程序？说起来也很简单，两个字——<strong><span style="text-decoration: underline;"><span style="color: #ff0000;">效率</span></span></strong>。让我们从头说起，标准CRT库出现于1970年左右，那时，线程的概念尚未出现在任何一个操作系统上。但是，线程毕竟是出现了，那好，让我们来看看下面这个例子，在这个例子中我们使用了CRT的全局变量 errno：</span></p>
<p><span style="font-size: medium;">BOOL fFailure = (system(&#8220;NOTEPAD.EXE README.TXT&#8221;) == -1);</p>
<p>if (fFailure) {<br />
     switch (errno) {<br />
     case E2BIG: // Argument list or environment too big<br />
         break;</p>
<p>   case ENOENT: // Command interpreter cannot be found<br />
       break;</p>
<p>   case ENOEXEC: // Command interpreter has bad format<br />
       break;</p>
<p>   case ENOMEM: // Insufficient memory to run command<br />
       break;<br />
   }<br />
} </span></p>
<p><span style="font-size: medium;">设想这样的情况，当上面的代码执行到system函数之后，if声明之前的时候，操作系统打断了它，而转去执行进程中的另一个线程，而这个线程正好使用了会设置errno的某个CRT函数&#8230;&#8230;于是，问题就出现了。<br />
为了解决这个问题，每个线程需要自己的errno全局变量，而且还需要一些机制来使得它们使用它们自己的errno变量，而不是其他线程的。当然， errno只是“多线程不服症”的其中一个受害者，其他受害者还有：_doserrno, strtok, _wcstok, strerror, _strerror, tmpnam, tmpfile, asctime, _wasctime, gmtime, _ecvt, _fcvt。<br />
于是，为了让C和C++程序能够正常工作，<strong><span style="text-decoration: underline;"><span style="color: #ff0000;">必须创建一个数据结构，并把它与每一个线程关连起来，只有这样才能调用CRT库时不至于误入“他线程家园”</span></span></strong>。<br />
   那么系统怎么知道在创建一个新线程时分配这个数据块呢？回答是系统不知道，这一切责任都在你，只有你才能确保所有的事情正常完成。<br />
是不是有点重任在肩的感觉？呵呵，不要紧，其你要做的和标题所说的一样，只需要调用_beginthreadex函数即可：</span></p>
<p><span style="font-size: medium;">unsigned long _beginthreadex(void *security,<br />
     unsigned stack_size,<br />
     <span style="text-decoration: underline;"><span style="color: #ff0000;">unsigned (*start_address)(void *), void *arglist</span></span>,<br />
     unsigned initflag, unsigned *thrdaddr);</span></p>
<p><span style="font-size: medium;">_beginthreadex的参数列表与CreateThread一模一样，只是参数名与类型有少许差异罢了。这是因为Microsoft觉得CRT函数不应该对Windows的数据类型有任何依赖。两者返回的东西也是一样的，所以即使你使用了CreateThread函数，要替换成_beginthreadex也是一件很容易的事情。<br />
因为两者的数据类型不完全一致，所以我们需要作一些转换来避免编译器的抱怨，为了简化这项工作，你可以使用我所写的这个宏：</span></p>
<p><span style="font-size: medium;">typedef unsigned (__stdcall * <strong><span style="text-decoration: underline;">PTHREAD_START</span></strong>) (void *);</span></p>
<p><span style="font-size: medium;">#define chBEGINTHREADEX(psa, cbStack, pfnStartAddr, \ pvParam, fdwCreate, pdwThreadID) \<br />
((HANDLE) _beginthreadex( \<br />
(void *) (psa), \<br />
(unsigned) (cbStack), \<br />
(PTHREAD_START) (pfnStartAddr),\<br />
(void *) (pvParam),\<br />
(unsigned) (fdwCreate), \<br />
(unsigned *) (pdwThreadID))) </span></p>
<p><span style="font-size: medium;">注意_beginthreadex函数只存在于CRT库的多线程版本中，如果你链接到了一个单线程运行时库，链接器会毫不客气地报告 “unresolved external symbol”错误。另外，还需要注意的是VS在创建新项目时默认选择的是单线程库，所以需要记得修改设置。<br />
说了这么多，只是说了一些概念，至于_beginthreadex为什么要比CreateThread更好，还是需要事实来说话的，当然，程序员所说的事实，就是代码了，代码之前，了无秘密，所以下面让我们来看看CRT库的代码是怎样的。首先，自然是主角人物_beginthreadex（你可以在THREADEX.C中找到它），因为没必要在这里重复写出源代码，所以我只给出伪代码版本的_beginthreadex：</span></p>
<p><span style="font-size: medium;"><strong><span style="text-decoration: underline;"><span style="color: #ff0000;">unsigned long __cdecl _beginthreadex (<br />
     void *psa,<br />
     unsigned cbStack,<br />
     unsigned (__stdcall * pfnStartAddr) (void *),<br />
     void * pvParam,<br />
     unsigned fdwCreate,<br />
     unsigned *pdwThreadID)</span></span></strong> </span></p>
<p><span style="font-size: medium;">{<br />
     _ptiddata ptd;         // Pointer to thread&#8217;s data block<br />
     unsigned long thdl;    // Thread&#8217;s handle<br />
     // Allocate data block for the new thread<br />
     if ((ptd = calloccrt(1, sizeof(struct tiddata))) == NULL)<br />
         goto errorreturn;<br />
     // Initialize the data block<br />
     initptd(ptd);<br />
     // Save the desired thread function and the parameter<br />
     // we want it to get in the data block<br />
<span style="color: #ff0000;"><strong><span style="text-decoration: underline;">     ptd-&gt;_initaddr = (void *) pfnStartAddr;<br />
     ptd-&gt;_initarg = pvParam;</span></strong></span><br />
     // Create the new thread<br />
     thdl = (unsigned long) CreateThread(psa, cbStack<strong><span style="text-decoration: underline;"><span style="color: #ff0000;">,_threadstartex, (PVOID) ptd</span></span></strong>, fdwCreate, pdwThreadID);<br />
     if (thdl == NULL) {<br />
         // Thread couldn&#8217;t be created, cleanup and return failure<br />
         goto error_return;<br />
     }</p>
<p>     // Create created OK, return the handle<br />
     return(thdl);</p>
<p>error_return:<br />
     // Error: data block or thread couldn&#8217;t be created<br />
     _free_crt(ptd);<br />
     return((unsigned long)0L);<br />
}</span></p>
<p><span style="font-size: medium;">_beginthreadex的代码中有几个地方需要重点注意：<br />
   (1)首先每个线程会从CRT的堆上获得真正属于它自己的tiddata内存块。 tiddata数据结构你可以在MTDLL.H中找到。传递给_beginthreadex的线程函数的地址被保存在tiddata内存块中。要传递给该线程函数的参数也被保存在这里。_beginthreadex接下来调用CreateThread，注意，这时<strong><span style="color: #ff0000;"><span style="text-decoration: underline;">CreateThread在新线程中执行的并不是pfnStartAddr函数，而是一个名为_threadstartex的函数</span></span></strong>。同时，传递给线程函数的参数也不是pvParam，而是 tiddata结构的地址。最后，如果一切顺利将返回线程句柄，如果任何一个操作失败，将返回NULL。<br />
现在，tiddata结构已经被分配并初始化完成，下面来看看该结构是如何关联到线程的。这次的对象是_threadstartex，同样也在THREADEX.C中，同样也给出伪代码：</span></p>
<p><span style="font-size: medium;">static unsigned long WINAPI _threadstartex (void* ptd) {<br />
    // Note: ptd is the address of this thread&#8217;s tiddata block</span></p>
<p><span style="font-size: medium;">    // Associate the tiddata block with this thread<br />
   <strong><span style="color: #ff0000;"><span style="text-decoration: underline;"> TlsSetValue</span>(__tlsindex, ptd);</span></strong></span></p>
<p><span style="font-size: medium;">    // Save this thread ID in the tiddata block<br />
    ((_ptiddata) ptd)-&gt;_tid = GetCurrentThreadId();</span></p>
<p><span style="font-size: medium;">    // Initialize floating-point support (code not shown) </span></p>
<p><span style="font-size: medium;">    // Wrap desired thread function in <strong><span style="text-decoration: underline;"><span style="color: #ff0000;">SEH frame</span></span></strong> to<br />
    // handle runtime errors and signal support<br />
    __try {<br />
        // Call desired thread function passing it the desired parameter<br />
        // Pass threads exit code value to _endthreadex<br />
        <strong><span style="text-decoration: underline;"><span style="color: #ff0000;">_endthreadex(<br />
          ( (unsigned (WINAPI *)(void *))(((_ptiddata)ptd)-&gt;_initaddr) )<br />
              ( ((_ptiddata)ptd)-&gt;_initarg ) ) ;<br />
</span></span></strong>    }<br />
    __except(_XcptFilter(GetExceptionCode(), GetExceptionInformation()){<br />
        // The C-Runtime&#8217;s exception handler deals with runtime errors<br />
        // and signal support, we should never get it here.<br />
        _exit(GetExceptionCode());<br />
    }</span></p>
<p><span style="font-size: medium;">    // We never get here, the thread dies in this function<br />
    return(0L);<br />
}</span></p>
<p><span style="font-size: medium;">_threadstartex同样也有一些东西需要我们注意。新线程开始时会执行BaseThreadStart（位于Kernel32.DLL 中），然后跳到_threadstartex。_threadstartex的唯一参数就是新线程的tiddata内存块地址。<strong><span style="text-decoration: underline;"><span style="color: #ff0000;">TlsSetValue完成了将tiddata结构与线程关联起来的目的（这里的tiddata结构被称为线程本地存储，TLS，顾名思义，就是属于每个线程自己的数据）。</span></span></strong><br />
在事实上的线程函数周围放置了一个结构化异常处理体（A structured exception handling frame）。这个处理体主要负责处理与运行时库有关的很多东西，比如运行时错误（像抛出但却没有被捕获的C++异常这类东西）和CRT的signal函数。这很重要，如果你使用CreateThread创建了线程，然后又调用了CRT的signal函数，那么signal函数将无法正常工作。<br />
注意，这时还不能返回到BaseThreadStart，如果这样做，线程会死掉，退出码会正常设置，但tiddata内存块不会被销毁，这就会造成内存泄漏。为了防止泄漏，需要调用_endthreadex，并且将退出码传递给它。<br />
_endthreadex同样也在THREADEX.C中，同样也给出伪代码：</span></p>
<p><span style="font-size: medium;">void __cdecl _endthreadex (unsigned retcode) {<br />
     _ptiddata ptd;    // Pointer to thread&#8217;s data block</span></p>
<p><span style="font-size: medium;">     // Cleanup floating-point support (code not shown) </span></p>
<p><span style="font-size: medium;">     // Get the address of this thread&#8217;s tiddata block<br />
     ptd = _getptd();</span></p>
<p><span style="font-size: medium;">     // Free the tiddata block<br />
     _freeptd(ptd);</span></p>
<p><span style="font-size: medium;">     // Terminate the thread<br />
     ExitThread(retcode);<br />
}</span></p>
<p><span style="font-size: medium;">注意CRT的_getptd函数在内部调用了系统的TlsGetValue函数来获取对应线程的tiddata内存块地址，然后释放该内存块，最后调用ExitThread来真正销毁线程，当然是用上面所提到的退出码来调用。<br />
我强烈建议你绝不要调用ExitThread来中止你的线程。最好也是最简单的办法就是让线程自己返回即可，让它自生自灭。ExitThread不仅徒增复杂，而且还会造成tiddata内存块泄漏。<br />
Microsoft Visual C++项目组发现人们总是喜欢调用ExitThread，他们希望能尽可能的做到让程序不泄漏内存。所以如果你真的想要明确地退出线程，你也最好使用<strong><span style="text-decoration: underline;"><span style="color: #ff0000;">_endthreadex</span></span></strong>，虽然这也不太好。<br />
OK，目前为止你应该对谁更好些的问题有了深入的了解，但是为什么调用CreateThread的程序仍然可以经年累月的正常运行呢？当线程调用一个需要 tiddata结构的CRT函数时（大多数CRT函数是线程安全的，并不需要该结构），首先CRT函数试图获取线程的数据块的地址（通过调用 TlsGetValue），然后，如果返回NULL，说明调用线程没有相关联的tiddata块，那么CRT函数马上为调用线程分配并初始化一个 tiddata块，并将该内存块关联到线程（通过TlsSetValue），这样，该CRT函数以及其他CRT函数都可以使用该线程的tiddata块了（此即所谓“前人栽树后人乘凉”了，^_^）。<br />
当然，如果说你的线程运行的时候一直没有问题是几乎不可能的。事实上，的确有一些问题需要说说。如果线程使用了CRT的signal函数，整个进程都会被中止，因为结构化异常处理体尚未准备好。同样，如果不调用_endthreadex来中止线程就会造成内存泄漏，如果使用_beginthreadex，当然会容易想到_endthreadex，但如果你习惯了使用CreateThread，是否还会想起_endthreadex，我表示极大的怀疑，而且CreateThread/_endthreadex的组合怎么看怎么让人别扭。<br />
不要忘记开始的问题，接下来让我们再来看看效率问题。CRT库的多线程版本在某些函数里面放置了同步原语，比如malloc，为了保证堆不会被同时调用的 malloc函数破坏，这不可避免地会对效率造成影响，C/C++的哲学我们不应忘记，“决不为自己没有用到的付出代价”，自然，我们无权要求单线程程序为多线程程序付出它们不该付出的代价，所以，开头的问题也有了答案。<br />
上面所说的都是静态链接的CRT库，而CRT库的动态链接版本则被编写得更加通用，以便能够被任何运行的程序和DLL共享。正是基于这个原因，这个版本的库只存在多线程版本。因为CRT库是以DLL形式提供的，程序和DLL不需要包含CRT库的任何代码，自然尺寸也就更小。同时，如果Microsoft修正了CRT库DLL中的Bug，程序也就自然受益了。<br />
终于该结束了，还是来几句总结吧：首先，如果你调用_beginthreadex，你会获得线程的句柄，句柄当然需要关闭，但_endthreadex并没有这么做。通常是调用_beginthreadex的线程（很可能是主线程）来调用CloseHandle关闭不再需要的新线程的句柄。其次，如果你使用CRT函数，你只需要使用_beginthreadex即可。如果不使用，那么你可以只使用CreateThread。同样，如果只有一个线程（主线程）使用 CRT，你也可以使用CreateThread；如果新创建的线程不使用CRT，那么你也不需要_beginthreadex和多线程CRT。</span></p>
</div>
</div>
]]></content:encoded>
			<wfw:commentRss>http://www.zzgan.com/?feed=rss2&amp;p=118</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>javascript捕获ocx事件</title>
		<link>http://www.zzgan.com/?p=116</link>
		<comments>http://www.zzgan.com/?p=116#comments</comments>
		<pubDate>Mon, 28 Jun 2010 04:10:55 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[ocx]]></category>

		<guid isPermaLink="false">http://www.zzgan.com/?p=116</guid>
		<description><![CDATA[&#60;OBJECT name=aaa
classid=&#8221;clsid:1677F2FC-05FE-4FA3-95B4-E6359B48387E&#8221;
codebase=&#8221;./ocx/ActiveFormProj1.ocx#version=1,0,6,0&#8243;
width=350
height=250
align=center
hspace=0
vspace=0
&#62;
&#60;!&#8211; script函数 &#8211;&#62;
&#60;script type=&#8221;text/javascript&#8221; Language=Javascript&#62;
function call(AID,AName)
{
alert(AID+AName);
}
&#60;/script&#62;
&#60;!&#8211;捕获ocx事件，如果name为aaa的ocx控件抛出OnCall(AID,AName)事件，则下面代码来进行捕获 &#8211;&#62;
&#60;SCRIPT type=&#8221;text/javascript&#8221; FOR=&#8221;aaa&#8221; EVENT=&#8221;OnCall(AID,AName)&#8221; &#62;
&#60;!&#8211; insert script commands &#8211;&#62;
call(AID,AName);
&#60;/SCRIPT&#62;
]]></description>
			<content:encoded><![CDATA[<p>&lt;OBJECT name=aaa<br />
classid=&#8221;clsid:1677F2FC-05FE-4FA3-95B4-E6359B48387E&#8221;<br />
codebase=&#8221;./ocx/ActiveFormProj1.ocx#version=1,0,6,0&#8243;<br />
width=350<br />
height=250<br />
align=center<br />
hspace=0<br />
vspace=0<br />
&gt;<br />
&lt;!&#8211; script函数 &#8211;&gt;<br />
&lt;script type=&#8221;text/javascript&#8221; Language=Javascript&gt;<br />
function call(AID,AName)</p>
<p>{<br />
alert(AID+AName);<br />
}<br />
&lt;/script&gt;</p>
<p>&lt;!&#8211;捕获ocx事件，如果name为aaa的ocx控件抛出OnCall(AID,AName)事件，则下面代码来进行捕获 &#8211;&gt;<br />
&lt;SCRIPT type=&#8221;text/javascript&#8221; FOR=&#8221;aaa&#8221; EVENT=&#8221;OnCall(AID,AName)&#8221; &gt;<br />
&lt;!&#8211; insert script commands &#8211;&gt;<br />
call(AID,AName);<br />
&lt;/SCRIPT&gt;</p>
]]></content:encoded>
			<wfw:commentRss>http://www.zzgan.com/?feed=rss2&amp;p=116</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>收拾心情，重新上路</title>
		<link>http://www.zzgan.com/?p=113</link>
		<comments>http://www.zzgan.com/?p=113#comments</comments>
		<pubDate>Fri, 25 Jun 2010 10:02:31 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[冇分类]]></category>

		<guid isPermaLink="false">http://www.zzgan.com/?p=113</guid>
		<description><![CDATA[学一点，忘一点
我不只是有一点小聪明的人，我会证给自己看，相信自己一定行
]]></description>
			<content:encoded><![CDATA[<p>学一点，忘一点</p>
<p>我不只是有一点小聪明的人，我会证给自己看，相信自己一定行</p>
]]></content:encoded>
			<wfw:commentRss>http://www.zzgan.com/?feed=rss2&amp;p=113</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
