C#线程通信和异步委托

来源:互联网 发布:2017社交聊天软件 编辑:程序博客网 时间:2024/06/06 01:58

第一次写关于技术原创····


至于要用到题目说到的这种方法,大概是因为在程序执行一些耗时的操作的时候,为了使得界面上不至于处于卡死状态,就让这些耗时的操作放在一边慢慢执行,并用一些方法来监视这些工作执行的状态。在这个过程中我的主线程可以完成一些其他的工作,这叫磨刀不误砍柴工··嘿嘿


关于异步委托,这里要用到里面的两个方法BeginInvoke 和 EndInvoke


BeginInvoke 方法启动异步调用。 该方法与您需要异步执行的方法具有相同的参数,还有另外两个可选参数。 第一个参数是一个 AsyncCallback 委托,该委托引用在异步调用完成时要调用的方法。 第二个参数是一个用户定义的对象,该对象将信息传递到回调方法。 BeginInvoke 立即返回,不等待异步调用完成。 BeginInvoke 返回一个 IAsyncResult,后者可用于监视异步调用的进度。


用代码讲解貌似简单一点·来一个三国·长坂坡

    class Program    {#region  三国·长板坡        //定义一个委托类型        public delegate int TaskDelegate(object obj, int ms);        //定义一个静态方法 看这个方法的开头就知道,大概是委托将要调用的方法        public static int ForFun(object obj, int ms)        {            Thread t = Thread.CurrentThread;            t.Name = "张飞";            Console.WriteLine("我有{0}在手,谁敢与我{1}大战三百回合", obj.ToString(), t.Name);            Thread.Sleep(ms);            return 1234;        }        //主线程入口,这个也是我们的主要战场        static void Main(string[] args)        {            Thread t1 = Thread.CurrentThread;            t1.Name = "长坂坡";            //主公的任务            Console.WriteLine("赶紧去{0}把赵子龙和阿斗救回来", t1.Name);            //为刚才委托指定方法,这里注意方法只需要提供方法名字就可以            TaskDelegate t = ForFun;            //使用委托的BeginIvoke方法为所委托耳方法赋值,并将执行结果交给IAsysResult接口            IAsyncResult ir = t.BeginInvoke("青釭剑", 1000 * new Random().Next(5), null, null);//new Random().Next(5)  返回一个小于所指定最大值的非负随机数              //上面这个函数除了最后两个参数之前的参数都是那个委托方法需要的参数            //曹操的军队比想象中快            Thread.Sleep(2000);            int i = 0;//计数器            // 如果委托还没有执行完就开始循环            while (!ir.IsCompleted)            {                i++;                Console.WriteLine(i.ToString());                Thread.Sleep(100);            }            //获取委托方法执行以后的返回值            int result = t.EndInvoke(ir);            Console.WriteLine("报告主公,曹军杀来,我奋力拼杀,斩敌{0}人", i.ToString());            if (i > 1)            {                Console.WriteLine("辛苦飞哥了,你杀敌{0}人,应该奖励黄金{1}两", i.ToString(), (i * 100).ToString());            }            else            {                Console.WriteLine("既然是未有杀敌,那今天就不奖励你啦");            }            Console.Read();        }
1用IAsyncResult中的IsCompleted 属性进行轮询判断是否完成

2 BeginInvoke()的函数声明:

public IAsyncResult BeginInvoke(

         <输入和输出变量>,回调函数callback , 附加信息AsyncState)

3 函数返回值类型:

public interface IAsyncResult

{

        object AsyncState{ get;}  //如果有回调函数的话该参数用于保存要传递给回调函数的参数值

        WaitHandle AsyncWaitHandle{ get;}

        bool CompletedSynchronously{ get;}

        bool IsCompleted{ get;} //保存方法是否执行结束,我们可以通过该属性的值来判断异步方法是否执行结束

}

4 EndInvoke方法用于检索异步调用结果。

方法声明:

      public <方法返回值类型>EndInvoke(<声明为ref或out的参数>, IAsyncResult result )

5 EndInvoke 方法检索异步调用的结果。 在调用 BeginInvoke 之后随时可以调用该方法。 如果异步调用尚未完成,则 EndInvoke 会一直阻止调用线程,直到异步调用完成

上面这个例子就是:使用轮询等待异步调用完成:使用IAsyncResult的IsCompleted属性来判断异步调用是否完成(

IAsyncResult来检


下面在循环部分修改代码就得到了异步通信的第二种方法:使用与IAsyncResult相关的等待句

 // 如果委托还没有执行完就开始循环            while (!ir.IsCompleted)            {                i++;                Console.WriteLine(i.ToString());                if(ir.AsyncWaitHandle.WaitOne(100,true))                {                    Console.WriteLine("主公的救兵怎么还不到,老张我撑不住了");                    break;                }               // Thread.Sleep(100);            }


使用 IAsyncResult.AsyncWaitHandle 属性获取 WaitHandle,使用其 WaitOne 方法阻止执行,直至 WaitHandle 收到信号,然后调用 EndInvoke

第三种异步委托的方法就是使用回调函数


那就先写一个回调函数来使用······要注意回调函数一定是在辅助线程里面使用

static void TakesWhileCompleted(IAsyncResult ar)        {            //如果为空则抛出异常            if (ar == null)                throw new ArgumentNullException("ar");            //将ar对象中IAsyncResult属性强类型为TaskDelegate委托类型            TaskDelegate dl = ar.AsyncState as TaskDelegate;            //跟踪检查dl是否有效,如果无效则显示提示消息            System.Diagnostics.Trace.Assert(dl != null, "无效的对象类型");            //执行委托方法,并将结果交给变量Result            int result = dl.EndInvoke(ar);            //打印结果,这里显示方法“ForFun”所返回的值            Console.WriteLine("老张我英勇非常,杀敌{0}人", result);        }
回调函数部分未完待续·····