C#应用实训|任务2 委托实现页面刷新
发布者:唯众
布时间:2020-12-21 11:49:07
点击量:
任务描述
在任务1中通过设置Control.CheckForIllegalCrossThreadCalls = false;避免了系统对子线程访问主线程更新UI控件的安全检查,这样可以避免程序因为刷新界面出现的“假死”现象,但在实际应用中,因为多线程可能同时访问主线程同一控件,在线程数不多的情况下可能看不出问题,但在线程数量增多及访问UI控件频率增大的情况下可能导致数据错误,因此当子线程访问主线程申请控制UI控件后,最好有一个应答的过程,在访问前申请,在访问后告之,任务2通过委托及control.Invoke 和 Control.BeginInvoke实现UI控件的刷新实现项目功能。
知识引入
- 委托
委托是.NET Framework引入的概念,它是面向对象的,类似于C语言中的函数指针,通过委托可以调用C#中的方法,委托是一种特殊的对象类型,定义一个委托可以同时引用多个方法,委托只是定义了这一类方法的参数类型和参数个数,不指定具体的方式功能,在实例化委托时通过方法参数具体到特定的方法,通过调用委托实现方法的调用执行。
使用委托方法如下:
在 C#中使得delegate关键字定义委托,语法为:
[访问修饰符] deletate 返回值类型 委托名([参数列表]);如
public deletate int GetData( int a, int b);
【例5-4】
using System;
using System.Collections.Generic;
using System.Text;
namespace Demo5_4
{
class Program
{
//定义委托
public delegate int GetData(int n);
public static int GetSum(int n)
{
int sum = 0;
for (int i = 1; i <= n;i++ )
{
sum += i;
}
return sum;
}
public static int GetFac(int n)
{
int fac = 1;
for (int i = 1; i <= n; i++)
{
fac *= i;
}
return fac;
}
static void Main(string[] args)
{
GetData getsum = new GetData(GetSum);
GetData getfac = new GetData(GetFac);
Console.WriteLine(getsum(5));
Console.WriteLine(getfac(5));
}
}
}
程序运行输出结果如图5-7所示:
图5-7 程序运行结果图
这时委托指向的是静态方法,如果委托指向实例方法,需要通过类的实例对象调用方法。
【
例5-5】
public delegate void show();
class Demo5
{
public void msgShow()
{
Console.WriteLine("考试时间到");
}
}
class Program
{
static void Main(string[] args)
{
show msgshow = new show( new Demo5().msgShow);
msgshow();
}
}
在程序开发中,如果有的方法调用必须使用委托作参数,也可不定义委托指向的方法,使用匿名委托或实例化委托时使用匿名方法。
【
例5-6】
public delegate void show();
class Program
{
static void Main(string[] args)
{
show msgshow = delegate(){
Console.WriteLine("下课了");
};
msgshow();
}
}
- Invoke( )和BeginInvoke( )
Control.Invoke (Delegate) :在拥有此控件的基础窗口句柄的线程上执行指定的委托。
Control.BeginInvoke (Delegate) :在创建控件的基础句柄所在线程上异步执行指定委托。的windows窗体应用程序中,子线程更新主线程创建UI控件,经常通过后台线程实现调用Invoke( )和Begininvoke( )方法与主线程发送消息。
【
例5-7】
下面使用委托及Invoke( )方法实现主线程UI控件刷新,程序运行如图5-8所示:
图5-8 程序运行效果图
点击按钮“button1”后,上面的标签在“红色”变为“蓝色”,并且每隔2 秒在两种颜色之间进行切换。
public delegate void UpdateUI();
public Form2()
{
InitializeComponent();
}
private void setText()
{
while (true)
{
if(InvokeRequired)
{
if (label1.Text.Equals("红色"))
{
this.Invoke(new UpdateUI(delegate()
{
label1.Text = "蓝色";
}));
}
else
{
this.Invoke(new UpdateUI(delegate()
{
label1.Text = "红色";
}));
}
Thread.Sleep(2000);
}
}
}
private void button1_Click(object sender, EventArgs e)
{
UpdateUI updateUi = new UpdateUI(setText);
Thread t = new Thread(new ThreadStart(updateUi));
t.IsBackground = true;
t.Start();
}
任务实现
新建Windows窗体应用程序项目,修改任务1后台代码如下:
public partial class Form1 : Form
{
public delegate void UpdateUI();
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
Thread t = new Thread(new ThreadStart(setVal));
t.IsBackground = true;
t.Start();
}
//随机生成温度
private int getWd()
{
int result = -1;
Random rand = new Random();
result = rand.Next(20,35);
return result;
}
//随机生成光敏
private int getPhoto()
{
int result = -1;
Random rand = new Random();
result = rand.Next(50, 150);
return result;
}
//读取值
private void setVal()
{
while (true)
{
if (InvokeRequired)
{
int wdNum = getWd();
int photoNum = getPhoto();
this.Invoke(new UpdateUI(delegate()
{
lblTemp.Text = wdNum.ToString();
if (wdNum >= 28)
{
lblFs.Text = "打开";
}
else
{
lblFs.Text = "关闭";
}
lblPhoto.Text = photoNum.ToString();
if (photoNum >= 100)
{
lblRgb.Text = "打开";
}
else
{
lblRgb.Text = "关闭";
}
}));
Thread.Sleep(3000);
}
}
}
}
任务小结
- 委托使关键字delegate进行定义。
- 委托类似于C语言的函数指针,委托在实例化时的参数为方法名。
- 子线程通过Invoke( )和Begininvoke( )方法与主线程发送消息。
上一篇:C#应用实训|任务1 线程实现页面刷新
下一篇:C#应用实训|任务3 事件引发页面刷新