C# 简单的多线程和使用异步方式调用同步方法

查看MSDN看到Thread类有4个构造函数 有两个主要参数:ThreadStart和ParameterizedThreadStart;

查看MSDN可以看出:

1、ThreadStart是一个无参没有返回值的委托类型;

2、ParameterizedThreadStart是带有一个object类型参数,没有返回值的委托类型;

如下图:

使用实例源码:

  class Program
    {        
        public static void Main(string[] args)
        {
            ThreadStart method = null;
            Thread withoutParam = null;
            //1-1无参数->ThreadStart对象初始化化线程对象
            method = Sum2;//methon=new ThreadStart(Sum2)   method += Sum2(多播委托)
            withoutParam = new Thread(method);
            withoutParam.Name = "无参数->ThreadStart对象初始化化线程对象";
            withoutParam.Start();

            //1-2无参数->函数初始化化线程对象
            withoutParam = new Thread(Sum2) { IsBackground = true, Name = "无参数->函数初始化化线程对象" };
            withoutParam.Start();

            //1-3无参数->匿名函数初始化化线程对象
            withoutParam = new Thread(delegate()
            {
                for (int i = 0; i < 5; i++)
                {
                    if (i == 3)
                        Thread.CurrentThread.Abort();
                    Thread.Sleep(50);
                    Console.WriteLine(Thread.CurrentThread.ManagedThreadId + "-->" + Thread.CurrentThread.Name);
                }
            }) { IsBackground = true, Name = "无参数->匿名函数初始化化线程对象" };
            withoutParam.Start();

            //1-4无参数->Lambda表达式初始化化线程对象
            withoutParam = new Thread(() =>
            {
                for (int i = 0; i < 5; i++)
                {
                    Thread.Sleep(50);
                    Console.WriteLine(Thread.CurrentThread.ManagedThreadId + "-->" + Thread.CurrentThread.Name);
                }
            },1) { IsBackground = true, Name = "Lambda表达式初始化化线程对象" };
            withoutParam.Start();


            ParameterizedThreadStart method2;
            Thread whitParam = null;
            //2-1带参数->ThreadStart对象初始化化线程对象
            method2 = Sum3;
            whitParam = new Thread(method2);
            whitParam.Name = "**********带参数**********->->ParameterizedThreadStart对象初始化化线程对象";
            whitParam.Start(2);
            //2-2带参数->函数初始化化线程对象
            whitParam = new Thread(Sum3) { Name = "**********带参数**********->->函数初始化化线程对象" };
            whitParam.Start(3);

            //2-3带参数->匿名方法初始化化线程对象
            whitParam = new Thread(delegate(object para){
                int count = (int)para;

                for (int i = 0; i < count; i++)
                {
                    Thread.Sleep(50);
                    Console.WriteLine(Thread.CurrentThread.ManagedThreadId + ":::" + Thread.CurrentThread.Name);
                }

            }) { Name = "**********带参数**********->匿名函数初始化化线程对象" };
            whitParam.Start(1);

            //2-4带参数->Lambda表达式初始化化线程对象
            whitParam = new Thread((para)=>
            {
                int count = (int)para;

                for (int i = 0; i < count; i++)
                {
                    Thread.Sleep(50);
                    Console.WriteLine(Thread.CurrentThread.ManagedThreadId + ":::" + Thread.CurrentThread.Name);
                }

            }) { Name = "**********带参数**********->Lambda表达式初始化化线程对象" };
            whitParam.Start(100);


            Console.ReadKey();
        }
     
        private static void Sum2()
        {
            for (int i = 0; i < 5; i++)
            {
                Thread.Sleep(50);
                Console.WriteLine(Thread.CurrentThread.ManagedThreadId + "-->" + Thread.CurrentThread.Name);
            }
        }

        private static void Sum3(object para)
        {
            int count = (int)para;

            for (int i = 0; i <count ; i++)
            {
                Thread.Sleep(50);
                Console.WriteLine(Thread.CurrentThread.ManagedThreadId +":::"+ Thread.CurrentThread.Name);
            }
        }

    }

按这样的方式如果需要线程处理的结果怎么办?

1、定义一个线程参数类代码如下:

/// <summary>
    /// 线程参数
    /// </summary>
    class ThreadParam
    {
        /// <summary>
        /// 线程处理参数
        /// </summary>
        public int X;

        /// <summary>
        /// 线程处理参数
        /// </summary>
        public int Y;
       
        /// <summary>
        /// Action是一个没有返回值泛型委托,用于线程处理结果回调
        /// </summary>
        public Action<int> CallBack;
    }

2、完整示例:

 class Program
    {               

        public static void Main(string[] args)
        {
            Console.WriteLine("程序开始执行::*********" );                 
            Thread whitParam = new Thread(Sum3);
            ThreadParam param = new ThreadParam() { X = 10, Y = 20 };
            param.CallBack = ThreadCallBack;
            whitParam.Start(param);
            for (int i = 0; i < 20; i++)
            {
                Thread.Sleep(5);
                Console.WriteLine("主线程ID:"+Thread.CurrentThread.ManagedThreadId);
            }
            Console.ReadKey();
        }

        private static void ThreadCallBack(int result)
        {
            Thread.Sleep(10);
            Console.WriteLine("线程处理结果::"+result);
        }

        private static void Sum3(object para)
        {           
            ThreadParam p = para as ThreadParam;
            int rsult = p.X + p.Y;
            if (p.CallBack != null)
            {
                p.CallBack(rsult);  
            }
            Console.WriteLine(Thread.CurrentThread.ManagedThreadId + "-->线程结束");
        }

    }

 

二、使用异步方式调用同步方法:

使用 .NET Framework 可以以异步方式调用任何方法。 要实现此操作,必须定义一个委托,此委托具有与你要调用的方法相同的签名;公共语言运行时会自动使用适当的签名为此委托定义 BeginInvoke 和 EndInvoke 方法。 

A、BeginInvoke 方法启动异步调用,返回 IAsyncResult ,该结果可以获取异步调用的完成进度。

B、EndInvoke 方法获取异步调用结果,在BeginInvoke方法之后的任何地方调用,如果异步调用的方法没有执行完成,EndInvoke方法 将阻止调用线程,直到完成异步调用。

1、使用BeginInvoke方法和EndInvoke方法进行异步调用的4种方式

  A、执行一些操作,然后调用 EndInvoke 进行阻止,直到调用完成;代码如下:

 public static void Main(string[] args)
        {
            //声明一个泛型委托(返回值为int类型,有2个int类型参数);
            //使用lambda表达式为委托赋值。该表达式sleep 1秒,然后返回2个数的和;
            Func<int, int, int> testAction = (x, y) => { Thread.Sleep(1000); return x + y; };
          
            IAsyncResult result = testAction.BeginInvoke(10, 15, null, null);
            //BeginInvoke和EndInvoke方法之间,可以执行一些其他的操作A

            int sum = testAction.EndInvoke(result);//如果A的操作不需要1秒就完成,那么EndInvoke就阻塞等待,直到结果回来,程序再执行EndInvoke方法下面的代码
            Console.WriteLine("异步调用的结果:" + sum);
            Console.ReadKey();
        }

  B、使用 WaitHandle 属性获取 IAsyncResult.AsyncWaitHandle ,使用它的 WaitOne 方法阻止执行,直到 WaitHandle 收到信号,然后调用 EndInvoke;代码如下:

 public static void Main(string[] args)
        {
            //声明一个泛型委托(返回值为int类型,有2个int类型参数);
            //定义一个匿名方法为委托赋值。该方法sleep 1秒,然后返回2个数的和;
            Func<int, int, int> testAction = (x, y) => { Thread.Sleep(1000); return x + y; };
          
            IAsyncResult result = testAction.BeginInvoke(10, 15, null, null);
            //BeginInvoke和EndInvoke方法之间,可以执行一些其他的操作A         
            result.AsyncWaitHandle.WaitOne();           
            int sum = testAction.EndInvoke(result);//如果A的操作不需要1秒就完成,那么EndInvoke就阻塞等待,直到结果回来,程序再执行EndInvoke方法下面的代码
            Console.WriteLine("异步调用的结果:" + sum);
            result.AsyncWaitHandle.Close();
            Console.ReadKey();
        }

C、对由BeginInvoke返回  IAsyncResult的IsCompleted  进行轮询,以确定异步调用完成的时间,然后调用 EndInvoke。代码如下:

 public static void Main(string[] args)
        {
            //声明一个泛型委托(返回值为int类型,有2个int类型参数);
            //定义一个匿名方法为委托赋值。该方法sleep 1秒,然后返回2个数的和;
            Func<int, int, int> testAction = (x, y) => { Thread.Sleep(1000); return x + y; };
          
            IAsyncResult result = testAction.BeginInvoke(10, 15, null, null);
            //BeginInvoke和EndInvoke方法之间,可以执行一些其他的操作A     
            while (!result.IsCompleted)
            {
                Console.Write("*");
                Thread.Sleep(250);
            }
                    
            int sum = testAction.EndInvoke(result);//如果A的操作不需要1秒就完成,那么EndInvoke就阻塞等待,直到结果回来,程序再执行EndInvoke方法下面的代码
            Console.WriteLine("异步调用的结果:" + sum);          
            Console.ReadKey();
        }

D、将回调方法的委托传递到 BeginInvoke。 异步调用完成后在 ThreadPool 线程上执行TestCallBack方法。 在TestCallBack方法中调用 EndInvoke。代码如下:

 public static void Main(string[] args)
        {
            //声明一个泛型委托(返回值为int类型,有2个int类型参数);
            //定义一个匿名方法为委托赋值。该方法sleep 1秒,然后返回2个数的和;
            Func<int, int, int> testAction = (x, y) => { Thread.Sleep(1000); return x + y; };
            //声明一个委托 
            AsyncCallback callBack =TestCallBack;
            IAsyncResult result = testAction.BeginInvoke(10, 15, callBack, "I am call back param");
          //  IAsyncResult result = testAction.BeginInvoke(10, 15, TestCallBack, "I am call back param");              
            Console.ReadKey();
        }
        public static void TestCallBack(IAsyncResult ar)
        {
            AsyncResult result = (AsyncResult)ar;
            Func<int, int, int> caller = (Func<int, int, int>)result.AsyncDelegate;
            string parameter = (string)ar.AsyncState;
            Console.WriteLine(parameter);
            Console.WriteLine("异步方法的处理结果结果:" + caller.EndInvoke(ar));
        }

总结:调用线程需要对异步处理结果进行处理可以使用的方式:A、B、C。如果调用线程不需要处理异步结果,则使用D方式。在ThreadPool线程中调用CallBack方法,对异步结果进行处理。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值