C#使用多线程并发之异步委托

阻塞式编程:我们一边编写的代码都是同步代码,也就是从上到下按照顺序执行。

例如

public delegate void DoWorkHandler();

    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("开始烧水了");

            // 一直等到水烧开
            DoWorkHandler handler = (() =>
                {
                    Thread.Sleep(2000);
                    Console.WriteLine("水烧好了");
                });
            handler.Invoke();

            // 在水未烧开之前一直会有阻塞
            Console.WriteLine("扫一下地吧");
        }
    }

或者这样形式

 public delegate int DoWorkHandler(int ms);

    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("程序开始");

            // 一直等到水烧开
            DoWorkHandler handler = BoilWaterHandler;

            IAsyncResult asyncResult = handler.BeginInvoke(2000, null, null);
            //EndInvoke方法将被阻塞2秒。一直等待委托完成其任务为止
            int result = handler.EndInvoke(asyncResult);

            Console.WriteLine(result);
            Console.WriteLine("扫一下地吧");
            Console.ReadKey();

        }

        static int BoilWaterHandler(int ms)
        {
            Console.WriteLine("开始烧水");
            Thread.Sleep(ms);
            Console.WriteLine("烧水完成");
            return ++ms;
        }
     }

都是要阻塞2秒。怎样防止程序被阻塞,让CPU继续执行其他任务呢?

为了解决以上问题,我们需要使用异步的方式编程,原理其实就是遇到耗时较多的任务时,操作系统实现了时间片轮转调度算法,切换到另一个线程。

方案1、用委托(Delegate)的BeginInvoke和EndInvoke方法操作线程,使用IAsyncResult.IsCompleted属性来判断异步调用是否完成。在C#中,Delegate类包含Invoke和BeginInvoke两个方法,其中Invoke是同步的,而BeginInvoke则是异步的

  public delegate void DoWorkHandler();

    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("开始烧水了");

            // 一直等到水烧开
            DoWorkHandler handler = (() =>
            {
                Thread.Sleep(5000);
                Console.WriteLine("水烧好了");
            });

            // 这里不会有阻塞,我们可以做一些其他事情
            IAsyncResult asyncResult = handler.BeginInvoke(null, null);
            while (!asyncResult.IsCompleted)
            {
                Console.WriteLine("水还没烧好,先干点其的他事情吧");
                Thread.Sleep(1000);
            }

            Console.WriteLine("扫一下地吧");
            Console.ReadKey();

        }
      }

方案2、使用回调方式返回结果

第一种写法

 public delegate void DoWorkHandler();

    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("开始烧水了");

            // 一直等到水烧开
            DoWorkHandler handler = (() =>
            {
                Thread.Sleep(5000);
                Console.WriteLine("水烧好了");
            });


            // 异步回调
            IAsyncResult asyncResult = handler.BeginInvoke(new AsyncCallback(CallBack), null);
            while (!asyncResult.IsCompleted)
            {
                Console.WriteLine("水还没烧好,先干点其的他事情吧");
                Thread.Sleep(1000);
            }

            Console.WriteLine("扫一下地吧");
            Console.ReadKey();

        }

        static void CallBack(IAsyncResult result)
        {
            DoWorkHandler handler = (result as AsyncResult).AsyncDelegate as DoWorkHandler;
            handler.EndInvoke(result);
        }

 

 第二种写法

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Runtime.Remoting.Messaging;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace 异步编程测试
{
    public delegate int DoWorkHandler(int ms);

    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("开始烧水了");

            // 一直等到水烧开
            DoWorkHandler handler = DoHeatWater;


            handler.BeginInvoke(3000, CallBack, handler);


            Console.WriteLine("扫一下地吧");
            Console.ReadKey();

        }

        static int DoHeatWater(int ms)
        {
            Thread.Sleep(ms);
            Console.WriteLine("水烧好了");
            return ++ms;
        }

        static void CallBack(IAsyncResult result)
        {
            if (result == null)
            {
                throw new ArgumentNullException("result");
            }
            DoWorkHandler handler = result.AsyncState as DoWorkHandler;
            Trace.Assert(handler != null, "invalid objevt type");
            int data = handler.EndInvoke(result);
            Console.WriteLine(data);
        }

    }

}

参考:

https://blog.csdn.net/qq_34057374/article/details/76460578

https://blog.csdn.net/HerryDong/article/details/82825548

  • 0
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值