<?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>琥珀春秋 &#187; c#，多线程，异步</title>
	<atom:link href="http://amberlife.net/tag/c%ef%bc%8c%e5%a4%9a%e7%ba%bf%e7%a8%8b%ef%bc%8c%e5%bc%82%e6%ad%a5/feed/" rel="self" type="application/rss+xml" />
	<link>http://amberlife.net</link>
	<description>又一个 WordPress Blog</description>
	<lastBuildDate>Sat, 17 Jul 2010 13:36:16 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>理解c#中的异步方法</title>
		<link>http://amberlife.net/2010/01/%e7%90%86%e8%a7%a3c%e4%b8%ad%e7%9a%84%e5%bc%82%e6%ad%a5%e6%96%b9%e6%b3%95/</link>
		<comments>http://amberlife.net/2010/01/%e7%90%86%e8%a7%a3c%e4%b8%ad%e7%9a%84%e5%bc%82%e6%ad%a5%e6%96%b9%e6%b3%95/#comments</comments>
		<pubDate>Tue, 05 Jan 2010 11:52:47 +0000</pubDate>
		<dc:creator>amberlife</dc:creator>
				<category><![CDATA[program]]></category>
		<category><![CDATA[c#，多线程，异步]]></category>

		<guid isPermaLink="false">http://amberlife.net/?p=176</guid>
		<description><![CDATA[c#中构建多线程应用程序，不一定要通过System.Threading命名空间下的类来实现，通过delegate委托也能够实现多线程编程所需要的方式，（其实delegate就是利用CLR的ThreadPool来实现的，这个不再我们的讨论范围）。

先来说一下委托吧，通过当我们在应用程序中定义了一个委托后，其实在被编译成CIL后，就是一个类，我们可以通过ildasm.exe 这个程序来查看生成的CIL。
我们举个例子:

delegate  int   del &#40;string str1, string str2&#41;

del被编译后，生成的类的定义如下：

sealed class  del: System.MulticastDelegate
&#123;
	public del&#40;object target,uint functionAddress&#41;;
	public void Invoke&#40;string str1,string str2&#41;;
	public IAsyncResult BeginInvoke&#40;string str1,string str2,AsyncCallback cb ,object state&#41;;
	public int EndInvoke&#40;IAsyncResult result&#41;;
&#125;

生成的Invoke()方法用来调用被代理对象同步方式维护的方法，调用线程（应用程序的主线程）会一直等待，直到委托调用完成。在c#中，Invoke()不会被显式的调用，而是在同步方式下自动被触发。
下面我们来说说BeginInvoke方法和EndInvoke()方法，这两个方法是在利用委托来实现异步调用的关键。
在本例中BeginInvoke方法如下：

		IAsyncResult BeginInvoke&#40;string str1,string str2, AsyncCallback cb ,object state&#41;;

可以看到BeginInvoke方法返回IAsyncResult，参数列表中含有四个参数，前两个参数如同del委托中参数的定义，后两个参数System.AsyncCallback和System.Object类型的。
在本例中的EndInvoke方法如下：

int EndInvoke&#40;IAsyncResult result&#41;

EndInvoke方法返回int ，参数列表中含有一个参数，参数类型为IAsyncResult。在BeginInvoke方法和EndInvoke方法中，BeginInvoke方法中除了最后两个参数，前面的参数必须和之前定义的委托中的参数一样；EndInvoke方法的返回值必须和之前定义的委托的返回值一样。
借助上面定义的委托，我们写这样一个函数

int  stradd &#40;string str1,string str2&#41;
&#123;
	//仅仅为了测试一下异步方法的线程和调用线程是否是一致的。
	Console.WriteLine&#40;&#34;stradd thread id : &#34;,Thread.CurrentThread.GetHashCode&#40;&#41;&#41;;
	return str1.length+str2.length;
&#125;

下面定义一个主函数测试一下：

static void Main&#40;string&#91;&#93; args&#41;
&#123;
	Console.writeLine&#40;&#34;Main [...]]]></description>
			<content:encoded><![CDATA[<p>c#中构建多线程应用程序，不一定要通过System.Threading命名空间下的类来实现，通过delegate委托也能够实现多线程编程所需要的方式，（其实delegate就是利用CLR的ThreadPool来实现的，这个不再我们的讨论范围）。<br />
<span id="more-176"></span><br />
先来说一下委托吧，通过当我们在应用程序中定义了一个委托后，其实在被编译成CIL后，就是一个类，我们可以通过ildasm.exe 这个程序来查看生成的CIL。</p>
<p>我们举个例子:</p>

<div class="wp_syntax"><div class="code"><pre class="csharp" style="font-family:monospace;"><span style="color: #FF0000;">delegate</span>  <span style="color: #FF0000;">int</span>   del <span style="color: #000000;">&#40;</span><span style="color: #FF0000;">string</span> str1, <span style="color: #FF0000;">string</span> str2<span style="color: #000000;">&#41;</span></pre></div></div>

<p>del被编译后，生成的类的定义如下：</p>

<div class="wp_syntax"><div class="code"><pre class="csharp" style="font-family:monospace;"><span style="color: #0600FF;">sealed</span> <span style="color: #FF0000;">class</span>  del<span style="color: #008000;">:</span> <span style="color: #000000;">System</span>.<span style="color: #0000FF;">MulticastDelegate</span>
<span style="color: #000000;">&#123;</span>
	<span style="color: #0600FF;">public</span> del<span style="color: #000000;">&#40;</span><span style="color: #FF0000;">object</span> target,<span style="color: #FF0000;">uint</span> functionAddress<span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
	<span style="color: #0600FF;">public</span> <span style="color: #0600FF;">void</span> Invoke<span style="color: #000000;">&#40;</span><span style="color: #FF0000;">string</span> str1,<span style="color: #FF0000;">string</span> str2<span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
	<span style="color: #0600FF;">public</span> IAsyncResult BeginInvoke<span style="color: #000000;">&#40;</span><span style="color: #FF0000;">string</span> str1,<span style="color: #FF0000;">string</span> str2,AsyncCallback cb ,<span style="color: #FF0000;">object</span> state<span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
	<span style="color: #0600FF;">public</span> <span style="color: #FF0000;">int</span> EndInvoke<span style="color: #000000;">&#40;</span>IAsyncResult result<span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
<span style="color: #000000;">&#125;</span></pre></div></div>

<p>生成的Invoke()方法用来调用被代理对象同步方式维护的方法，调用线程（应用程序的主线程）会一直等待，直到委托调用完成。在c#中，Invoke()不会被显式的调用，而是在同步方式下自动被触发。<br />
下面我们来说说BeginInvoke方法和EndInvoke()方法，这两个方法是在利用委托来实现异步调用的关键。<br />
在本例中BeginInvoke方法如下：</p>

<div class="wp_syntax"><div class="code"><pre class="csharp" style="font-family:monospace;">		IAsyncResult BeginInvoke<span style="color: #000000;">&#40;</span><span style="color: #FF0000;">string</span> str1,<span style="color: #FF0000;">string</span> str2, AsyncCallback cb ,<span style="color: #FF0000;">object</span> state<span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span></pre></div></div>

<p>可以看到BeginInvoke方法返回IAsyncResult，参数列表中含有四个参数，前两个参数如同del委托中参数的定义，后两个参数System.AsyncCallback和System.Object类型的。<br />
在本例中的EndInvoke方法如下：</p>

<div class="wp_syntax"><div class="code"><pre class="csharp" style="font-family:monospace;"><span style="color: #FF0000;">int</span> EndInvoke<span style="color: #000000;">&#40;</span>IAsyncResult result<span style="color: #000000;">&#41;</span></pre></div></div>

<p>EndInvoke方法返回int ，参数列表中含有一个参数，参数类型为IAsyncResult。在BeginInvoke方法和EndInvoke方法中，BeginInvoke方法中除了最后两个参数，前面的参数必须和之前定义的委托中的参数一样；EndInvoke方法的返回值必须和之前定义的委托的返回值一样。</p>
<p>借助上面定义的委托，我们写这样一个函数</p>

<div class="wp_syntax"><div class="code"><pre class="csharp" style="font-family:monospace;"><span style="color: #FF0000;">int</span>  stradd <span style="color: #000000;">&#40;</span><span style="color: #FF0000;">string</span> str1,<span style="color: #FF0000;">string</span> str2<span style="color: #000000;">&#41;</span>
<span style="color: #000000;">&#123;</span>
	<span style="color: #008080; font-style: italic;">//仅仅为了测试一下异步方法的线程和调用线程是否是一致的。</span>
	Console.<span style="color: #0000FF;">WriteLine</span><span style="color: #000000;">&#40;</span><span style="color: #666666;">&quot;stradd thread id : &quot;</span>,Thread.<span style="color: #0000FF;">CurrentThread</span>.<span style="color: #0000FF;">GetHashCode</span><span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
	<span style="color: #0600FF;">return</span> str1.<span style="color: #0000FF;">length</span><span style="color: #008000;">+</span>str2.<span style="color: #0000FF;">length</span><span style="color: #008000;">;</span>
<span style="color: #000000;">&#125;</span></pre></div></div>

<p>下面定义一个主函数测试一下：</p>

<div class="wp_syntax"><div class="code"><pre class="csharp" style="font-family:monospace;"><span style="color: #0600FF;">static</span> <span style="color: #0600FF;">void</span> Main<span style="color: #000000;">&#40;</span><span style="color: #FF0000;">string</span><span style="color: #000000;">&#91;</span><span style="color: #000000;">&#93;</span> args<span style="color: #000000;">&#41;</span>
<span style="color: #000000;">&#123;</span>
	Console.<span style="color: #0000FF;">writeLine</span><span style="color: #000000;">&#40;</span><span style="color: #666666;">&quot;Main thread id :&quot;</span>,Thread.<span style="color: #0000FF;">CurrentThread</span>.<span style="color: #0000FF;">GetHashCode</span><span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
	del dd <span style="color: #008000;">=</span> <span style="color: #008000;">new</span> del<span style="color: #000000;">&#40;</span>stradd<span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
	IAsyncResult result <span style="color: #008000;">=</span> dd.<span style="color: #0000FF;">BeginInvoke</span><span style="color: #000000;">&#40;</span><span style="color: #666666;">&quot;hello &quot;</span>,<span style="color: #666666;">&quot;The another thread&quot;</span>,<span style="color: #0600FF;">null</span>,<span style="color: #0600FF;">null</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
&nbsp;
	<span style="color: #008080; font-style: italic;">//EndInvoke方法阻塞调用线程，直到stradd方法运行结束</span>
	<span style="color: #FF0000;">int</span> len <span style="color: #008000;">=</span> dd.<span style="color: #0000FF;">EndInvoke</span><span style="color: #000000;">&#40;</span>result<span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
	Console.<span style="color: #0000FF;">WriteLine</span><span style="color: #000000;">&#40;</span><span style="color: #666666;">&quot;the length of str1 + str2 ={0}&quot;</span>,len<span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
<span style="color: #000000;">&#125;</span></pre></div></div>

<p>运行后我们可以知道异步调用就是创建了一个次线程。<br />
通过上面的例子，我们可以看到一个异步调用的过程，但是，这样的调用对于多线程的要求，是毫无用处的，<br />
     endInvoke方法仍旧会阻塞主线程的运行。那么有没有好的方式来实现呢？我们想一下，如果能够在次线程还没有结束的时候，我们能够查看到次线程的运行的状态，在次线程还没有结束的时候，我们可以做主线程剩下的工作，这样的话，就不会让主线程一直在那里等待。</p>
<p>   为了实现这样的机制，我们先来看一个接口IAsyncResult,这个接口在异步方法中很常见，回顾一下刚才看到得东西，BeginInvoke方法的返回值<br />
EndInvoke方法的参数，都是这个接口。我们看一下这个接口的定义：</p>

<div class="wp_syntax"><div class="code"><pre class="csharp" style="font-family:monospace;"><span style="color: #0600FF;">public</span> <span style="color: #FF0000;">interface</span>  IAsyncResult
<span style="color: #000000;">&#123;</span>
	<span style="color: #FF0000;">object</span> AsyncState<span style="color: #000000;">&#123;</span>get <span style="color: #008000;">;</span><span style="color: #000000;">&#125;</span>
	WaitHandle AsyncWaitHandle<span style="color: #000000;">&#123;</span>get<span style="color: #008000;">;</span><span style="color: #000000;">&#125;</span>
	<span style="color: #FF0000;">bool</span> CompletedSynchronously<span style="color: #000000;">&#123;</span>get<span style="color: #008000;">;</span><span style="color: #000000;">&#125;</span>
	<span style="color: #FF0000;">bool</span> IsCompleted<span style="color: #000000;">&#123;</span>get<span style="color: #008000;">;</span><span style="color: #000000;">&#125;</span>
<span style="color: #000000;">&#125;</span></pre></div></div>

<p>IAsyncResult提供了IsCompleted接口，使用这个属性，调用线程可以在调用EndInvoke方法之前，自动判断异步调用是否完成。如果完成，返回true；<br />
未完成返回false；</p>

<div class="wp_syntax"><div class="code"><pre class="csharp" style="font-family:monospace;"><span style="color: #0600FF;">static</span> <span style="color: #0600FF;">void</span> Main<span style="color: #000000;">&#40;</span><span style="color: #FF0000;">string</span><span style="color: #000000;">&#91;</span><span style="color: #000000;">&#93;</span> args<span style="color: #000000;">&#41;</span>
<span style="color: #000000;">&#123;</span>
	Console.<span style="color: #0000FF;">writeLine</span><span style="color: #000000;">&#40;</span><span style="color: #666666;">&quot;Main thread id :&quot;</span>,Thread.<span style="color: #0000FF;">CurrentThread</span>.<span style="color: #0000FF;">GetHashCode</span><span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
	del dd <span style="color: #008000;">=</span> <span style="color: #008000;">new</span> del<span style="color: #000000;">&#40;</span>stradd<span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
	IAsyncResult result <span style="color: #008000;">=</span> dd.<span style="color: #0000FF;">BeginInvoke</span><span style="color: #000000;">&#40;</span><span style="color: #666666;">&quot;hello &quot;</span>,<span style="color: #666666;">&quot;The another thread&quot;</span>,<span style="color: #0600FF;">null</span>,<span style="color: #0600FF;">null</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
	<span style="color: #0600FF;">while</span> <span style="color: #000000;">&#40;</span>result.<span style="color: #0000FF;">IsCompleted</span><span style="color: #000000;">&#41;</span>
	<span style="color: #000000;">&#123;</span>
		<span style="color: #008080; font-style: italic;">//做主线程接下来的工作。</span>
	<span style="color: #000000;">&#125;</span>
	<span style="color: #008080; font-style: italic;">//EndInvoke方法阻塞调用线程，直到stradd方法运行结束</span>
	<span style="color: #FF0000;">int</span> len <span style="color: #008000;">=</span> dd.<span style="color: #0000FF;">EndInvoke</span><span style="color: #000000;">&#40;</span>result<span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
	Console.<span style="color: #0000FF;">WriteLine</span><span style="color: #000000;">&#40;</span><span style="color: #666666;">&quot;the length of str1 + str2 ={0}&quot;</span>,len<span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
<span style="color: #000000;">&#125;</span></pre></div></div>

<p>      通过这样的一种轮询机制，我们能够实现调用线程不会被阻塞，同时能保证第一时间获取次线程运行的结果，但仔细想过之后就会发现这种方式的笨拙，要不断的执行<br />
while循环中的内容，直到次线程完成。基于这一原因，IAsyncResult提供了AsyncWaitHandle属性实现更加灵活的控制。AsyncWaitHandle返回一个WaitHandle类型的实例<br />
该实例含有一个WaitOne的公共方法,查看msdn，我们看到，这个方法可以阻塞调用线程，直到WaitHandle收到信号。<br />
更改上面的main方法，如下所示：</p>

<div class="wp_syntax"><div class="code"><pre class="csharp" style="font-family:monospace;"><span style="color: #0600FF;">static</span> <span style="color: #0600FF;">void</span> Main<span style="color: #000000;">&#40;</span><span style="color: #FF0000;">string</span><span style="color: #000000;">&#91;</span><span style="color: #000000;">&#93;</span> args<span style="color: #000000;">&#41;</span>
<span style="color: #000000;">&#123;</span>
	Console.<span style="color: #0000FF;">writeLine</span><span style="color: #000000;">&#40;</span><span style="color: #666666;">&quot;Main thread id :&quot;</span>,Thread.<span style="color: #0000FF;">CurrentThread</span>.<span style="color: #0000FF;">GetHashCode</span><span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
	del dd <span style="color: #008000;">=</span> <span style="color: #008000;">new</span> del<span style="color: #000000;">&#40;</span>stradd<span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
	IAsyncResult result <span style="color: #008000;">=</span> dd.<span style="color: #0000FF;">BeginInvoke</span><span style="color: #000000;">&#40;</span><span style="color: #666666;">&quot;hello &quot;</span>,<span style="color: #666666;">&quot;The another thread&quot;</span>,<span style="color: #0600FF;">null</span>,<span style="color: #0600FF;">null</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
	<span style="color: #0600FF;">while</span> <span style="color: #000000;">&#40;</span><span style="color: #008000;">!</span>result. <span style="color: #0000FF;">AsyncWaitHandle</span>.<span style="color: #0000FF;">WaitOne</span><span style="color: #000000;">&#40;</span><span style="color: #FF0000;">2000</span>，<span style="color: #0600FF;">true</span><span style="color: #000000;">&#41;</span><span style="color: #000000;">&#41;</span>
	<span style="color: #000000;">&#123;</span>
		<span style="color: #008080; font-style: italic;">//做主线程接下来的工作。</span>
	<span style="color: #000000;">&#125;</span>
	<span style="color: #008080; font-style: italic;">//EndInvoke方法阻塞调用线程，直到stradd方法运行结束</span>
	<span style="color: #FF0000;">int</span> len <span style="color: #008000;">=</span> dd.<span style="color: #0000FF;">EndInvoke</span><span style="color: #000000;">&#40;</span>result<span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
	Console.<span style="color: #0000FF;">WriteLine</span><span style="color: #000000;">&#40;</span><span style="color: #666666;">&quot;the length of str1 + str2 ={0}&quot;</span>,len<span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
<span style="color: #000000;">&#125;</span></pre></div></div>

<p>       使用WaitHandle.waitOne(2000,true),指定最长等待时间为秒，秒后如果AsyncWaitHandle未受到次线程结束的信号，返回false；否则返回true。<br />
       通过上述两种方式，我们发现一个共同点，就是调用线程(主线程)在询问次线程是否完成了，并且这种询问是一次又一次的进行，这种方式显的笨拙。如果当次线程结束的时候<br />
能够让他自己来通知主线程，说明自己结束了，这样的话，主线程就没有必要在花费时间来询问次线程，这样的方式显然更好理解。</p>
<p>       想要实现这样的一种方式，我们就必须来理解BeginInvoke的后两个参数，我们先来介绍AsyncCallback参数，这个参数是一个委托，默认值是null。只要提供了AsyncCallback对象<br />
当异步调用完成的时候，就会自动的调用AsyncCallback委托所指定的方法。AsyncCallback委托能够调用那些符合特定模式的方法，方法的签名如下所示：</p>

<div class="wp_syntax"><div class="code"><pre class="csharp" style="font-family:monospace;"><span style="color: #0600FF;">void</span> AsyncCallbackMethod<span style="color: #000000;">&#40;</span>IAsyncResult iac<span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span></pre></div></div>

<p>我们还用上面的例子，这次用次线程结束后调用AsyncCallback委托指定的方法这样的方式来实现.</p>

<div class="wp_syntax"><div class="code"><pre class="csharp" style="font-family:monospace;"><span style="color: #0600FF;">static</span> <span style="color: #0600FF;">void</span> Main<span style="color: #000000;">&#40;</span><span style="color: #FF0000;">string</span><span style="color: #000000;">&#91;</span><span style="color: #000000;">&#93;</span> args<span style="color: #000000;">&#41;</span>
<span style="color: #000000;">&#123;</span>
	Console.<span style="color: #0000FF;">writeLine</span><span style="color: #000000;">&#40;</span><span style="color: #666666;">&quot;Main thread id :&quot;</span>,Thread.<span style="color: #0000FF;">CurrentThread</span>.<span style="color: #0000FF;">GetHashCode</span><span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
	del dd <span style="color: #008000;">=</span> <span style="color: #008000;">new</span> del<span style="color: #000000;">&#40;</span>stradd<span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
	IAsyncResult result <span style="color: #008000;">=</span> dd.<span style="color: #0000FF;">BeginInvoke</span><span style="color: #000000;">&#40;</span><span style="color: #666666;">&quot;hello &quot;</span>,<span style="color: #666666;">&quot;The another thread&quot;</span>,<span style="color: #008000;">new</span> AsyncCallback<span style="color: #000000;">&#40;</span>complete<span style="color: #000000;">&#41;</span>,<span style="color: #0600FF;">null</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
	<span style="color: #008080; font-style: italic;">//做主线程接下来的工作</span>
<span style="color: #000000;">&#125;</span>
<span style="color: #0600FF;">void</span> complete <span style="color: #000000;">&#40;</span>IAsyncResult iac<span style="color: #000000;">&#41;</span>
<span style="color: #000000;">&#123;</span>
	Console.<span style="color: #0000FF;">WriteLine</span><span style="color: #000000;">&#40;</span><span style="color: #666666;">&quot;The stradd method has completed。&quot;</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span><span style="color: #008080; font-style: italic;">//告诉了主线程，次线程已经工作结束了。</span>
<span style="color: #000000;">&#125;</span></pre></div></div>

<p>在这个例子中，会发现我们在主线程中，由于没有调用EndInvoke方法(调用这个方法，会阻塞主线程，那么就等于没有体现异步的优点) 我们无法得到stradd方法运算的结果。现在注意complete方法的参数IAsyncResult iac。(又一次碰到了这个接口，可见他是多么的重要)<br />
这是一个接口，我们没法直接使用它，在c#中存在一个实现了IAsyncResult接口的类AsyncResult。利用这个类，我们能够得到想要的结果。<br />
下面我们修改complete方法，如下所示：</p>
<pre lang="csharp>
void complete (IAsyncResult iac)
{
	AsyncResult ar = (AsyncResult)iac;
	del dd = (del)ar.AsyncDelegate;
	int len = dd.EndInvoke(iac);
	Console.WriteLine("the length of str1 + str2 ={0}",len);
	Console.WriteLine("The stradd method has completed。");//告诉了主线程，次线程已经工作结束了。
}
</pre>
<p>修改后，我们彻底完成了通过次线程通知主线程，来告知自己结束，这样一种异步调用的机制。<br />
看到这里，我们发现，在BeginInvoke中，最后一个参数我们始终没有提及，这个参数的类型是System.Object的，所以可以传入任意想要看到的类型。<br />
该参数允许从主线程传递额外的状态信息给AsyncCallback委托中的回调方法。<br />
我们定义个额外的类</p>

<div class="wp_syntax"><div class="code"><pre class="csharp" style="font-family:monospace;"><span style="color: #FF0000;">class</span> Message
<span style="color: #000000;">&#123;</span>
	<span style="color: #0600FF;">public</span> <span style="color: #FF0000;">string</span> msg <span style="color: #008000;">=</span> <span style="color: #666666;">&quot;一些额外的内容&quot;</span><span style="color: #008000;">;</span>
<span style="color: #000000;">&#125;</span>
修改main方法如下：
<span style="color: #0600FF;">static</span> <span style="color: #0600FF;">void</span> Main<span style="color: #000000;">&#40;</span><span style="color: #FF0000;">string</span><span style="color: #000000;">&#91;</span><span style="color: #000000;">&#93;</span> args<span style="color: #000000;">&#41;</span>
<span style="color: #000000;">&#123;</span>
	Console.<span style="color: #0000FF;">writeLine</span><span style="color: #000000;">&#40;</span><span style="color: #666666;">&quot;Main thread id :&quot;</span>,Thread.<span style="color: #0000FF;">CurrentThread</span>.<span style="color: #0000FF;">GetHashCode</span><span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
	del dd <span style="color: #008000;">=</span> <span style="color: #008000;">new</span> del<span style="color: #000000;">&#40;</span>stradd<span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
	IAsyncResult result <span style="color: #008000;">=</span> dd.<span style="color: #0000FF;">BeginInvoke</span><span style="color: #000000;">&#40;</span><span style="color: #666666;">&quot;hello &quot;</span>,<span style="color: #666666;">&quot;The another thread&quot;</span>,<span style="color: #008000;">new</span> AsyncCallback<span style="color: #000000;">&#40;</span>complete<span style="color: #000000;">&#41;</span>,<span style="color: #008000;">new</span> Message<span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
	<span style="color: #008080; font-style: italic;">//做主线程接下来的工作</span>
	Console.<span style="color: #0000FF;">ReadLine</span><span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
<span style="color: #000000;">&#125;</span>
修改complete方法如下：
<span style="color: #0600FF;">void</span> complete <span style="color: #000000;">&#40;</span>IAsyncResult iac<span style="color: #000000;">&#41;</span>
<span style="color: #000000;">&#123;</span>
	<span style="color: #008080; font-style: italic;">//为了在complete方法中获取获取BeginInvoke最后一个参数，使用IAsyncResult参数的AsyncState属性.</span>
	Message  m <span style="color: #008000;">=</span> <span style="color: #000000;">&#40;</span>Message<span style="color: #000000;">&#41;</span>iac.<span style="color: #0000FF;">AsyncState</span><span style="color: #008000;">;</span>
	Console.<span style="color: #0000FF;">WriteLine</span><span style="color: #000000;">&#40;</span>m.<span style="color: #0000FF;">msg</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
	Console.<span style="color: #0000FF;">WriteLine</span><span style="color: #000000;">&#40;</span><span style="color: #666666;">&quot;The stradd method has completed。&quot;</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span><span style="color: #008080; font-style: italic;">//告诉了主线程，次线程已经工作结束了。</span>
<span style="color: #000000;">&#125;</span></pre></div></div>

<p>Well done ! 这样我们就完成了对异步调用的讨论，下面我们总结一下，在异步调用中，我们需要深入理解委托的BeginInvoke方法，EndInvoke方法，IAsyncResult接口<br />
AsyncResult类，AsyncCallback委托。理解清楚这些方法，类，接口已经这几个之间的关系。就能够掌握异步调用的精髓了。</p>
]]></content:encoded>
			<wfw:commentRss>http://amberlife.net/2010/01/%e7%90%86%e8%a7%a3c%e4%b8%ad%e7%9a%84%e5%bc%82%e6%ad%a5%e6%96%b9%e6%b3%95/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
