• .Net 多线程编程由浅入深知识梳理


    1.Using System.Threading;
         多线程就是一个包工头,让手底下的十个工人去搬砖头的事儿。
        
    ------------不带任何传入参数的Thread
    2.ThreadStart ts = new ThreadStart(某线程A的Func);
       Thread th = new Thread(ts);
       th.Start();
       
       public void 某线程A的Func()
       {
            Console.WriteLine("线程A把事情做好了!");
            Console.ReadKey();
       }
       
       原理解析
       2.1 ThreadStart原型为一个委托类型:
             public delegate void ThreadStart();
       2.2 ThreadStart这个委托类型是没有任何传入参数的
       
       如下可以让ThreadStart能够接收参数
        public class MyThread
        {
            private double _width = 10.0;
            private double _height = 9.0;
            private double result = 0.0;
            public MyThread(double width,double height)
            {
                this._width = width;
                this._height = height;
            }

            public void MyThreadExc()
            {
                Console.WriteLine("MyThread Execute Start ...");
                Thread.Sleep(2000);
                result = _width * _height;
                Console.WriteLine("MyThread Execute Done:The Result is {0}", result);
            }
        }
        
        static void Main(string[] args)
        {
            MyThread th = new MyThread(5.0,3.0);
            Thread t = new Thread(new ThreadStart(th.MyThreadExc));
            t.Start();
            Console.ReadKey();
        }
       
             
     ------------带有参数的Thread
     3.ParameterizedThreadStart pts = new  ParameterizedThreadStart(某线程B的Func);
        Thread th = new Thread(pts);
        th.Start(objParam);
        
        public void 某线程B的Func(object param)
        {
             Console.WriteLine("线程B接收了param并把事情做好了!");
        }
        
        原理解析
        3.1 ParameterizedThreadStart原型为一个委托类型:
             public delegate void ParameterizedThreadStart(object obj);
        3.2 ParameterizedThreadStart这个委托类型是接收Object传参的
        
    ------------带有传入参数并且有返回参数
     刚才说到主线程需要知道子线程什么时候执行完成,我们可以用Thread.ThreadState枚举来进行判断
     当线程的ThreadState==Thread.Stop时,此时就可以判断该Thread已经结束,这时它的结果就可以使用了,如果不是这个状态,就继续执行别的工作,或等待再次尝试。倘若需要有多个子
     线程返回,并且需要他们的返回内容再进行异步计算,这就叫做线程同步了,下面将介绍一种方法,能够自定义参数个数,并且返回数据,使用起来很方便
     使用委托的异步调用方法和回调
     1. 需要异步调用的Func定义为一个委托
     2. BeginInvoke来异步调用 -- 第一个参数是传参,第二个参数是当线程执行完毕之后调用的方法 (穿插复习Invoke 与 BeginInvoke的区别)
     
     delegate double MyJobDelegate(double d);

     static  MyJobDelegate myJob;
     
     double jobResult=0.0;
     
     static void Main(string[] args)
     {
         myJob = new MyJobDelegate(Job1);
         myJob.BeginInvoke(5.09,new AsyncCallback(Job1Done),null)
     }
     
     static double Job1(double d)
     {
         return d*Math.PI;
     }
     
     static void Job1Done(IAsyncResult result)
     {
         Console.WriteLine(myJob.EndInvoke(result));
     }
     
     Asynchronous 异步
     Synchronous  同步
     [在C#中使用线程的方法很多,使用委托的BeginInvoke和EndInvoke方法就是其中之一。BeginInvoke方法可以使用线程异步地执行委托所指向的方法。然后通过EndInvoke方法获得方法的返回值
     (EndInvoke方法的返回值就是被调用方法的返回值),或是确定方法已经被成功调用。]
     
     -------------线程池
     线程虽然是个好东西,但是也是一个资源消耗大户,我们需要用多线程,但是又不希望线程过多,线程池的机制就应运而生啦,.Net为我们提供了一个现成的ThreadPool,他的使用如下:
     
     ///
     ///首先下面这是线程池线程所要执行的回调方法
     ///
    using System;
    using System.Runtime.InteropServices;

    namespace System.Threading
    {
        // 摘要:
        //     表示线程池线程要执行的回调方法。
        //
        // 参数:
        //   state:
        //     包含回调方法要使用的信息的对象。
        [ComVisible(true)]
        public delegate void WaitCallback(object state);
    }

    static WaitCallback wait;

    static void Main(string[] args)
    {
        wait = new WaitCallback(myJob);
        ThreadPool.QueueUserWorkItem(wait,1.0);
        ThreadPool.QueueUserWorkItem(wait,2.0);
        ThreadPool.QueueUserWorkItem(wait,3.0);
        ThreadPool.QueueUserWorkItem(wait,4.0);
        Console.ReadKey();
    }

    private static void myJob(object obj)
    {
        double d= (double)obj;
        Console.WriteLine("Job Exec Result: {0}",d*Math.PI);
    }


    -------------控制权
    场景:如果Winfrom程式主线程创建了一个控件TextBox1,随后某个子线程开始创建并且工作,产生一个返回值,如果此时将该返回值返回给TextBox1,程式就会报错:禁止跨线程访问控件;
    那么此时我们就需要用到控件的一个方法:BeginInvoke或Invoke,这个方法可以把执行上下文切换回创建这个控件的线程:
    delegate void ChangeTextBoxDelegate(string newtext);

    private void Button1_Click(object sender,EventArgs e)
    {
        ParameterizedThreadStart pts = new ParameterizedThreadStart(myJob);
        Thread th = new Thread(pts);
        th.Start(1.09);
    }

    ----------------方案1---------------
    private void myJob(object obj)
    {
        this.BeginInvoke(new ChangeTextBoxDelegate(this.TextBox1.AppendText)),((double)obj * Math.PI).ToString());
    }


        或者 (推荐)
    ----------------方案2--------------
        private void SetTextBox1Text(string text)
        {
            if(TextBox1.InvokeRequired)
            {
                ChangeTextBoxDelegate ct = SetTextBox1Text;
                TextBox1.BeginInvoke(ct,text);
            }
            else
            {
                TextBox1.Text = text;
            }
        }
        
        private void myJob(object obj)
        {
                SetTextBox1Text((double)obj * Math.PI).ToString());
        }
        参考:http://www.cnblogs.com/yizhu2000/archive/2007/10/12/922637.html
       


    Impossible = I'm possible
    Don't be the same, be better. Just do it.
    You'll be there.
  • 相关阅读:
    jQuery插件之jquery editable plugin点击编辑文字插件
    firefox与ie的javascript兼容性编程汇编【转载】
    css前端制作 经验总结
    非常棒的jqChart图表插件
    WPF Image Source设置文件路径后 在编辑状态下显示图片,运行时不显示
    WPF RadioButton 绑定枚举
    WPF MVVM实现数据增删改查逻辑全流程详细解析demo
    bigNumber.js的简单使用
    PHP程序的“Missing argument 3”的错误提示解决方法
    PHP判断0和空的方法
  • 原文地址:https://www.cnblogs.com/gavin-king/p/4255666.html
Copyright © 2020-2023  润新知