<?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>Mingbo &#187; 异步</title>
	<atom:link href="http://shao.mingbo.de/tag/%e5%bc%82%e6%ad%a5/feed/" rel="self" type="application/rss+xml" />
	<link>http://shao.mingbo.de</link>
	<description>包括教育技术，编程，互联网等方面的文章及随想。</description>
	<lastBuildDate>Sun, 25 Jul 2010 05:18:53 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=abc</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>cSharp中异步委托的笔记</title>
		<link>http://shao.mingbo.de/2009/12/19/asynchronous-delegate-in-csharp/</link>
		<comments>http://shao.mingbo.de/2009/12/19/asynchronous-delegate-in-csharp/#comments</comments>
		<pubDate>Sat, 19 Dec 2009 12:13:33 +0000</pubDate>
		<dc:creator>邵 明博</dc:creator>
				<category><![CDATA[csharp-note]]></category>
		<category><![CDATA[csharp]]></category>
		<category><![CDATA[myNote]]></category>
		<category><![CDATA[委托]]></category>
		<category><![CDATA[异步]]></category>

		<guid isPermaLink="false">http://shao.mingbo.de/?p=392</guid>
		<description><![CDATA[异步委托，首先要搞明白，为什么要用到异步委托。
长时间以来，我个人在编写代码的时候，都认为程序应该是执行完一件事之后，然后再干接下来的。这用计算机术语来讲，叫同步执行（Synchronous Execution）。但事实上，这样的执行效果不一定人性化。举下面的一组对照：

你有3份快件需要传递给远程客户。如果这件事由你本人亲自完成，那么，接下来，你将要停下手中的工作，跑3段路程，分别将这3个快件递交给3个不同的客户。然后返回公司继续执行你手上剩下的工作。现实生活中，这样的事情或许永远不会发生，因为聪明的你会打一个电话叫来快递专员来为你解决快件问题。
刚入学那会，写了一个资源转换工具。那个时候还没意识到出现了这样的问题：当我执行转换的时候，UI 无法继续响应用户的操作，而只有当转换完毕之后才恢复正常。实际上，现在分析起来，就是主线程没空搭理你，它正忙，忙完之后才能执行你的更新的操作。这个处境和之前的那个跑3段路传递3个快件的境遇差不多。.net 为我们设计了这个异步委托来执行类似快递专员的工作。

搞懂异步委托，需要理解BeginInvoke() ,EndInvoke() ,IAsyncResult 以及AsyncCallback 委托:
异步委托提供以异步方式调用同步方法的能力。当同步调用一个委托时，“Invoke”方法直接对当前线程调用目标方法。如果编译器支持异步委托，则它将生成“Invoke”方法以及“BeginInvoke”和“EndInvoke”方法。如果调用“BeginInvoke”方法，则公共语言运行库 (CLR) 将对请求进行排队并立即返回到调用方。将对来自线程池的线程调用该目标方法。提交请求的原始线程自由地继续与目标方法并行执行，该目标方法是对线程池线程运行的。如果在对“BeginInvoke”方法的调用中指定了回调方法，则当目标方法返回时将调用该回调方法。在回调方法中，“EndInvoke” 方法获取返回值和所有输入/输出参数。如果在调用“BeginInvoke”时未指定任何回调方法，则可以从调用“BeginInvoke”的线程中调用“EndInvoke”。
下面，我用一个例子，谈谈可能发生的4种情况
    class Programe
    {
        private delegate void ADelegateSomewhat(int x);

        public static void Main()
        {
     [...]]]></description>
			<content:encoded><![CDATA[<p>异步委托，首先要搞明白，为什么要用到异步委托。</p>
<p>长时间以来，我个人在编写代码的时候，都认为程序应该是执行完一件事之后，然后再干接下来的。这用计算机术语来讲，叫同步执行（Synchronous Execution）。但事实上，这样的执行效果不一定人性化。举下面的一组对照：</p>
<ul>
<li>你有3份快件需要传递给远程客户。如果这件事由你本人亲自完成，那么，接下来，你将要停下手中的工作，跑3段路程，分别将这3个快件递交给3个不同的客户。然后返回公司继续执行你手上剩下的工作。现实生活中，这样的事情或许永远不会发生，因为聪明的你会打一个电话叫来快递专员来为你解决快件问题。</li>
<li>刚入学那会，写了一个<a href="http://shao.mingbo.de/2009/10/10/ipv6-web-auto-adaptation/">资源转换工具</a>。那个时候还没意识到出现了这样的问题：当我执行转换的时候，UI 无法继续响应用户的操作，而只有当转换完毕之后才恢复正常。实际上，现在分析起来，就是主线程没空搭理你，它正忙，忙完之后才能执行你的更新的操作。这个处境和之前的那个跑3段路传递3个快件的境遇差不多。.net 为我们设计了这个<strong>异步委托</strong>来执行类似快递专员的工作。</li>
</ul>
<p>搞懂<strong>异步委托</strong>，需要理解<strong>BeginInvoke() </strong>,<strong>EndInvoke()</strong> ,<strong>IAsyncResult</strong> 以及<strong>AsyncCallback</strong> 委托:</p>
<blockquote><p>异步委托提供以异步方式调用同步方法的能力。当同步调用一个委托时，“Invoke”方法直接对当前线程调用目标方法。如果编译器支持异步委托，则它将生成“Invoke”方法以及“BeginInvoke”和“EndInvoke”方法。如果调用“BeginInvoke”方法，则公共语言运行库 (CLR) 将对请求进行排队并立即返回到调用方。将对来自线程池的线程调用该目标方法。提交请求的原始线程自由地继续与目标方法并行执行，该目标方法是对线程池线程运行的。如果在对“BeginInvoke”方法的调用中指定了回调方法，则当目标方法返回时将调用该回调方法。在回调方法中，“EndInvoke”<strong> </strong>方法获取返回值和所有输入/输出参数。如果在调用“BeginInvoke”时未指定任何回调方法，则可以从调用“BeginInvoke”的线程中调用“EndInvoke”。</p></blockquote>
<p>下面，我用一个例子，谈谈可能发生的4种情况</p>
<pre name="code" class="c-sharp">    class Programe
    {
        private delegate void ADelegateSomewhat(int x);

        public static void Main()
        {
            ADelegateSomewhat aD = MathPupil;
            ////1.直接调用EndInvoke,这和直接调用MathPupil(100)的效果一样，
            ////但会等到这个方法执行完之后才去执行后面的语句
            //IAsyncResult ar= aD.BeginInvoke(100,null,null);
            //aD.EndInvoke(ar);

            ////2.轮询,每隔50毫秒看看孩子算完了没.
            //IAsyncResult ar = aD.BeginInvoke(200, null, null);
            //while (!ar.IsCompleted)
            //{
            //    Console.Write(".");
            //    Thread.Sleep(500);
            //}
            //aD.EndInvoke(ar);

            ////3.实际上和2的方法类似，只是把Sleep的时间放上来了
            ////但事实上，功能会多点,比如控制跳出的条件等
            //IAsyncResult ar = aD.BeginInvoke(300,null,null);
            //while (!ar.AsyncWaitHandle.WaitOne(500))
            //{
            //    Console.Write(".");
            //}
            //aD.EndInvoke(ar);

            //4.回调函数,最有意义,设置相对麻烦点
            IAsyncResult ar = aD.BeginInvoke(400, MathCallBack, aD);
            //现在干点别的事，不用关心算算术题的孩子了。
            //由delegate的回调方法自动来管理
            Console.ReadLine();
            //如果不等待委托完成其任务就结束主线程，委托线程就会停止
        }

        //假装自己一个小学生处理一道加法算术题，历时5秒钟
        static void MathPupil(int x)
        {
            Console.WriteLine("Now I'll pretend to be a pupil");
            int sum = 0;
            for (int i = 0; i &lt; x; i++)
            {
                sum += i;
                Thread.Sleep(5000/x);
            }
            Console.WriteLine("After 5 secends, i've got the answer :" +sum);
        }

        static void MathCallBack(IAsyncResult ar)
        {
            ADelegateSomewhat aD = (ADelegateSomewhat)ar.AsyncState;
            aD.EndInvoke(ar);
        }

    }</pre>
<p>我想，到目前为止，应该收回<a href="http://shao.mingbo.de/2009/12/02/customize-event-in-csharp/">之前提到委托</a>“从来不是一个重点”的言论了。</p>
<p>参考资料：<a href="http://msdn.microsoft.com/en-us/magazine/cc164036.aspx" target="_blank">&lt;MSDN-magazine&gt;:Asynchronous Method Execution Using Delegates</a></p>
]]></content:encoded>
			<wfw:commentRss>http://shao.mingbo.de/2009/12/19/asynchronous-delegate-in-csharp/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
