【2019】委托/事件/异步/跨线程调用UI控件/多线程(Detegate/Event/Sync/InvokeRequired)

5 篇文章 0 订阅
委托/事件/异步/InvokeRequired/MultiThreading (Detegate/Event/Sync/InvokeRequired/MultiThreading )
委托事件
      #region Delegate1
      private void btnExe_Click(object sender, EventArgs e)
      {
          MyClass myObject = new MyClass();
          myObject.WorkCompletedDelegate += TestDelegate;
          myObject.WorkCompleted += TestEvent;
          myObject.WorkCompletedDelegate();

          myObject.Fire();
          myObject.Fier2();
          myObject.WorkCompletedDelegate();
          // myObject.WorkCompleted();  // this line will raise compiling error
      }
      static void TestEvent()
      {
          Console.WriteLine("test event");
      }

      static void TestDelegate()
      {
          Console.WriteLine("test delegate");
      }

      public class MyClass
      {
          public delegate void CompletedEventHandler();

          public event CompletedEventHandler WorkCompleted;
          public CompletedEventHandler WorkCompletedDelegate;

          public event CompletedEventHandler WorkCompleted2;

          public void Fier2()
          {
              WorkCompleted2 = new CompletedEventHandler(TestDelegate2);
              WorkCompleted2.BeginInvoke(null, null);
              //WorkCompleted2(TestDelegate);
          }

          public void TestDelegate2()
          {
              Console.WriteLine("test delegate2");
          }

          public void Fire()
          {
              if (WorkCompleted != null)
              {
                  this.WorkCompleted();
              }

              if (WorkCompletedDelegate != null)
              {
                  this.WorkCompletedDelegate();
              }
          }
      }
      #endregion

Result:
在这里插入图片描述

      #region Delegate2
      private void btnDelegate_Click(object sender, EventArgs e)
      {
          Test obj = new Test();
          obj.print += printout1;      //绑定printout1方法
          obj.print += printout2;      //绑定printout2方法
          obj.start();
      }
      static void printout1()
      {
          Console.WriteLine("输出第一段字符串");
      }
      static void printout2()
      {
          Console.WriteLine("输出第二段字符串");
      }

      public delegate void Print();      //创建委托
      class Test
      {
          ///https://www.cnblogs.com/wujingtao/p/5196834.html
          ///事件实际上是一个特殊的委托实例,不用事件也没有关系。
          ///实际上事件只是削弱了委托的功能,event在编译器角度保护了你程序的安全,
          ///因为你只能使用+=、-= 来注册事件了,而不能使用 = 为事件关联方法。
          ///(在委托中还可以使用=来绑定方法,不过=是一种破坏性代码,不管之前是否已经绑定的有方法了,他都会将其清除)
          public event Print print;      //创建事件实例
          public void start()
          {
              print();    //触发事件
          }
      }

      #endregion

Result:
输出第一段字符串
输出第二段字符串

异步
		private static int ExecuteTask1(int num)
		{
			System.Threading.Thread.Sleep(5000);
			return num * num;
		}
		private static int ExecuteTask2(int num)
		{
			return num * num;
		}
		/// <summary>
		/// 同步
		/// </summary>
		/// <param name="sender"></param>
		/// <param name="e"></param>
		private void btnSync_Click(object sender, EventArgs e)
		{
			lblCount1.Text = ExecuteTask1(10).ToString();
			lblCount2.Text = ExecuteTask2(10).ToString();
		}
异步
		/// <summary>
		/// 异步
		/// </summary>
		/// <param name="sender"></param>
		/// <param name="e"></param>
		private void btnAsync_Click(object sender, EventArgs e)
		{
			//创建委托方法
           //另外的写法:MyCalculator objMyCalc = new ExecuteTask1;
           MyCalculator objMyCalc = new MyCalculator(ExecuteTask1);
			//通过委托异步调用方法BeginInvoke(<输入和输出变量>,AsyncCallback, object AsyncState)方法:异步调用的核心
			//【输入和输出变量】:表示委托对应的参数
			//【Callback】:回调函数,表示异步调用后自动调用的函数
			//【AsyncState】:用于向回调函数提供参数信息
			//【返回值】IAsyncResult->异步操作状态接口,封装了异步执行的参数
			//https://ke.qq.com/webcourse/index.html#course_id=171257&term_id=100200221&taid=930440240340217&vid=j1413w5k6wv

			//异步调用任务
			IAsyncResult result = objMyCalc.BeginInvoke(10, null, null);
			lblCount1.Text = "正在计算,请稍等……";
			
			//同时执行其它任务
			lblCount2.Text = ExecuteTask2(10).ToString();

			//获取异步调用的结果
			int res = objMyCalc.EndInvoke(result);
			lblCount1.Text = res.ToString();
		}
InvokeRequired

this.InvokeRequired
判断当前线程是否是UI线程。
如果this.InvokeRequired = true,你需要通过this.Invoke()传递委托去操作界面。否则直接操作即可。
对于不是UI线程上边的代码,如果需要操作UI控件,就需要使用Invoke 或者beginInvoke。
类似的,如果你在UI的线程上边访问UI控件,就可以直接访问数据。

		private void btnExecute1_Click(object sender, EventArgs e)
		{
			//ThreadStart()定义方法:public delegate int Thread();
			//Thread objThread = new Thread(delegate()
			//    {
			//        for (int i = 0; i < 10; i++)
			//        {
			//            Console.WriteLine("i=:" + i.ToString());
			//            Thread.Sleep(500);
			//        }
			//    });
			Thread objThread = new Thread(()=>
			{
				for (int i = 1; i < 100; i++)
				{
					//Console.WriteLine("i=:" + i.ToString());
					if (this.lblResult1.InvokeRequired)//判断是否调用Invoke方法
					{
						//Invoke()方法第一个参数返回值为void委托,第二个给委托对应方法传递参数
						this.Invoke(new Action<string>(s => { this.lblResult1.Text = s; }), i.ToString());//i.ToString()
					}
					Thread.Sleep(500);
				}
			});
			objThread.IsBackground = true;
			objThread.Start();
		}

		private void btnExecute2_Click(object sender, EventArgs e)
		{
          ParameterArgs parameter;
			Thread objThread = new Thread(() =>
			{
				for (int i = 1; i < 50; i++)
				{
					//Console.WriteLine("i=:" + i.ToString());
					if (this.lblResult1.InvokeRequired)//判断是否调用Invoke方法
					{
						//Invoke()方法第一个参数返回值为void委托,第二个给委托对应方法传递参数
                      //this.Invoke(new Action<string>(s => { this.lblResult2.Text = s; }), i.ToString());
                      parameter = new ParameterArgs();
                      parameter.A = i;
                      parameter.B = i;
                      this.Invoke(new Action<ParameterArgs>(s => { this.lblResult2.Text = add(s).ToString(); }), parameter);
					}
					Thread.Sleep(200);
				}
			});
			objThread.IsBackground = true;
			objThread.Start();
		}

      public int add(ParameterArgs parameter)
      {
          return parameter.A + parameter.B;
      }

      public class ParameterArgs
      {
          public int A {get;set;}

          public int B {get;set;}

      }
异步委托
		//申明委托
		public delegate int MyCalculator(int num, int ms);
		MyCalculator objMyCal = null;//定义委托

		public AsyncDalegate()
		{
			InitializeComponent();
			objMyCal = new MyCalculator(ExecuteTask);//委托初始化
		}

		private int ExecuteTask(int num, int ms)
		{
			System.Threading.Thread.Sleep(ms);
           Console.WriteLine(num * num);

           return num * num;
		}
		/// <summary>
		/// 同时执行多个任务
		/// </summary>
		/// <param name="sender"></param>
		/// <param name="e"></param>
		private void btnAsync_Click(object sender, EventArgs e)
		{
			//MyCalculator objMyCal = ExecuteTask;设置为全局变量,为了回调函数封装为一个

			for (int i = 0; i < 10; i++)
			{
				objMyCal.BeginInvoke(10 * i, 1000 * i, MyCallBack, i);//最后一个参数i是给字段AsyncState(object类型)赋值,可以是值/类/集合
			}
		}
		//回调函数
		private void MyCallBack(IAsyncResult result)
		{
			//return objMyCal.EndInvoke(result);
			int res = objMyCal.EndInvoke(result);
			//异步显示结果:第一个计算结果:100
			Console.WriteLine("第{0}格计算结果是:{1}", result.AsyncState.ToString(), res);
		}
		//异步编程总结
		//1.异步编程是建立在委托的基础上的基础上的
		//2.异步调用用的每个方法都是在独立的线程中能够执行的,因此,本质上就是一种多线程程序,也可以使简单的多线程编程
		//3.比较适合在后台运行较为耗费时间的《简单的任务》并且要求任务之间是独立的,任务之间不要有直接独立访问可视化控件的内容
		//4.如果后台任务要求必须按照特定的顺序执行,或则访问到特定的共享资源,异步编程不太适合,应该选择多线程编程
		//https://ke.qq.com/webcourse/index.html#course_id=171257&term_id=100200221&taid=930444535307513&vid=j1413pmg05h

####多线程

	 /*
	 *进程:一个正在运行的程序就是一个进程。操作系统根据进程来分配各种资源(内存)*
	 *线程:操作系统为了提高效率会将一个进程分给多个线程,并根据线程来分配CPU执行时间*
	 *线程特点:在具有多个CPU的计算机中,可以并行执行*
	 *Thread类:表示托管线程,每个Thread对象都代表一个托管线程,每个托管线程都对应一个函数*
	 *ProcessThread类型:和操作系统本地线程是一致的*
	 */
	public partial class MultiThreading : Form
	{
		public MultiThreading()
		{
			InitializeComponent();
		}

		private void btnExecute1_Click(object sender, EventArgs e)
		{
			//ThreadStart()定义方法:public delegate int Thread();
           //Thread objThread = new Thread(delegate()
           //    {
           //        for (int i = 0; i < 10; i++)
           //        {
           //            //Console.WriteLine("i=:" + i.ToString());
           //            if (this.lblResult1.InvokeRequired)
           //            {
           //                this.Invoke(new Action<string>(s =>
           //                {
           //                    this.lblResult1.Text = s;
           //                }), i.ToString());
           //            }
           //            Thread.Sleep(500);
           //        }
           //    });

           Thread objThread = new Thread(() =>
           {
               for (int i = 1; i < 10; i++)
               {
                   //Console.WriteLine("i=:" + i.ToString());
                   if (this.lblResult1.InvokeRequired)
                   {
                       this.Invoke(new Action<string>(s =>
                       {
                           this.lblResult1.Text = s;
                       }), i.ToString());
                   }
                   Thread.Sleep(500);
               }
           });
			objThread.IsBackground = true;
			objThread.Start();

           Thread objThread2 = new Thread(() =>
           {
               for (int i = 1; i < 50; i++)
               {
                   //Console.WriteLine(":=i=:" + i.ToString());
                   if (this.lblResult2.InvokeRequired)
                   {
                       this.Invoke(new Action<string>(s =>
                       {
                           this.lblResult2.Text = s;
                       }), i.ToString());
                   }
                   Thread.Sleep(200);
               }
           });
           objThread2.IsBackground = true;
           objThread2.Start();
		}

		private void btnExecute2_Click(object sender, EventArgs e)
		{
			Thread objThread = new Thread(() =>
			{
				for (int i = 1; i < 50; i++)
				{
					//Console.WriteLine(":=i=:" + i.ToString());
                   if (this.lblResult2.InvokeRequired)
                   {
                       this.Invoke(new Action<string>(s =>
                       {
                           this.lblResult2.Text = s;
                       }), i.ToString());
                   }
					Thread.Sleep(200);
				}
			});
			objThread.IsBackground = true;
			objThread.Start();
		}
	}
···
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

fengzhilu000

送人玫瑰,手留余香!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值