天天看点

多线程学习笔记一多线程学习笔记一

多线程学习笔记一

主要:委托的同步调用,异步调用

委托异步调用时的回调函数,几种等待方式。

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace 多线程学习
{
    /// <summary>
    /// 进程 线程  计算机概念
    /// 进程:一个程序运行时,占用的全部计算资源的总和
    ///  线程:程序执行流的最小单位;任何操作都是由线程完成的;
    ///  线程是依托于进程存在的,一个进程可以包含多个线程;
    ///   线程也可以有自己的计算资源
    ///   多线程:多个执行流同时运行
    ///   cpu太快,分时间片--上下文切换(加载变量--计算--保存环境)
    ///   微观角度,一个核同一时刻只能执行一个线程,宏观来说是多线程并发
    ///   多CPU(多核)可以独立工作
    ///   4核8线程:核是物理的核,线程是指虚拟核
    ///   
    ///   Thread是C#语言对线程对象的封装
    ///   
    /// 是对方法执行的描述
    /// 同步:完成计算之后,再进行下一行
    /// 异步:不会等待方法的完成,会直接进入下一行:非阻塞
    /// 
    /// C#异步和多线程有什么差别
    /// 多线程就是多个thread并发
    /// 异步是硬件式的异步
    /// 异步多线程--thread pool task
    /// </summary>
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
            Thread.Sleep(11);
        }

        private void btn_Sync_Click(object sender, EventArgs e)
        {
            Console.WriteLine("this is a sync method");
            Action<string> action = this.DoSomethingLong;
            for (int i = 0; i < 5; i++)
            {//委托的同步调用:UI界面会卡,应为UI线程在执行计算,无法响应
                string name = string.Format($"btn_Sync_Click_{i}");
                action.Invoke(name);
            }
        }

        private void btn_Async_Click(object sender, EventArgs e)
        {
            Console.WriteLine("this is a async method");
            {
                //委托的同步调用
                //Action<string> action = DoSomethingLong;
                //action.Invoke("btn_Async_Click_1");
                //action("btn_Async_Click_2");
                委托的异步调用:异步多线程
                //action.BeginInvoke("btn_Async_Click_3",null,null);
                委托的同步调用
                //action.Invoke("btn_Async_Click_4");
            }
            {
                Action<string> action = this.DoSomethingLong;
                for(int i=0;i<5;i++)
                {//异步多线程:委托异步调用:不卡界面,主线程完事,计算任务交给子线程
                    //同步调用:UI界面会卡,应为UI线程在执行计算,无法响应

                    //同步方法慢,因为只有一个线程工作;异步方法快,因为多个线程并发运算
                    //并不是线性增长,牺牲资源换取时间,资源可能不够,上下文切换会消耗资源,多线程有管理成本
                    //线程可以加快速度,但并不是越多越好。
                    //使用多线程的情况:多个任务可以独立同时运行。

                    //线程只有操作系统才有,编程时都是进程向操作系统申请的
                    //同步方法可控性好
                    //异步方法无序:启动无序:执行时间不确定,结束无序
                    //一定不要通过等几毫秒的形式来控制线程的启动和结束

                    //回调/状态等待/信号量
                    string name = string.Format($"btn_Async_Click_{i}");
                    action.BeginInvoke(name, null, null);
                }
            }
            Console.WriteLine("async method end");
        }

        /// <summary>
        /// 很耗时的方法
        /// </summary>
        /// <param name="name"></param>
        private void DoSomethingLong(string name)
        {
            Console.WriteLine("DoSomethingLong Start"+Thread.CurrentThread.ManagedThreadId.ToString("00"));
            for(int i=0;i<5;i++)
            {
                Thread.Sleep(400);
                Console.WriteLine(name);
            }
            Console.WriteLine("DoSomethingLong End");
        }

        private void btn_AsyncAdvanced_Click(object sender, EventArgs e)
        {
            Console.WriteLine("btn_AsyncAdvanced_Click Start " + Thread.CurrentThread.ManagedThreadId.ToString("00"));
            Action<string> action = this.DoSomethingLong;
            IAsyncResult asyncResult = null;
            //AsyncCallback callback = new AsyncCallback(ia => Console.WriteLine("到这里计算已经完成" + Thread.CurrentThread.ManagedThreadId.ToString("00")));
            //AsyncCallback callback = ia => Console.WriteLine("到这里计算已经完成" + Thread.CurrentThread.ManagedThreadId.ToString("00"));
            AsyncCallback callback = ia =>
              {
                  Console.WriteLine(object.ReferenceEquals(asyncResult, ia));
                  Console.WriteLine(ia.AsyncState);
                  Console.WriteLine("到这里计算已经完成" + Thread.CurrentThread.ManagedThreadId.ToString("00"));
              };
            asyncResult=action.BeginInvoke("btn_AsyncAdvanced_Click",callback,"superman");

            int i = 0;
            //while(!asyncResult.IsCompleted)//1 卡界面,主线程忙于等待
            //{//可以等待,边等待边做其他操作,但是会最多延迟200ms               
            //    if(i<10)
            //    {
            //        Console.WriteLine($"文件上传完成{(i++)*10}%...");
            //    }
            //    else
            //    {
            //        Console.WriteLine($"文件上传完成99.9%...");
            //    }
            //    Thread.Sleep(200);
            //}

            Thread.Sleep(200);
            Console.WriteLine("Do Something Else...");
            Console.WriteLine("Do Something Else...");
            Console.WriteLine("Do Something Else...");
            asyncResult.AsyncWaitHandle.WaitOne();//等待任务完成,
            asyncResult.AsyncWaitHandle.WaitOne(-1);
            asyncResult.AsyncWaitHandle.WaitOne(1000);//等待,最多等待1000ms,超过1000ms就不等了

            action.EndInvoke(asyncResult);//可以等待,不仅可以等待,还可以获取返回值,
            //该等待可以放在回调函数内,也可以放在回调函数外面,但二者只能选其一,否则报错
            {
                Func<int> func = () =>
                   {
                       Thread.Sleep(2000);
                       return DateTime.Now.Day;
                   };
                Console.WriteLine($"func.Invoke()={func.Invoke()}");

                IAsyncResult asyncResult1=func.BeginInvoke(c =>
                {
                    //Console.WriteLine($"func.EndInvoke(c)={func.EndInvoke(c)}");
                    Console.WriteLine(c.AsyncState);

                }, "superman");
                Console.WriteLine($"func.EndInvoke(asyncResult1)={func.EndInvoke(asyncResult1)}");
            }

            Console.WriteLine("文件上传成功!");

            Console.WriteLine("全部计算真的完成了" + Thread.CurrentThread.ManagedThreadId.ToString("00"));
            //Console.WriteLine("到这里计算已经完成"+ Thread.CurrentThread.ManagedThreadId.ToString("00"));
            Console.WriteLine("btn_AsyncAdvanced_Click End " + Thread.CurrentThread.ManagedThreadId.ToString("00"));

        }
    }
}

           

继续阅读