博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Delegate Lambda Action Func
阅读量:6038 次
发布时间:2019-06-20

本文共 11237 字,大约阅读时间需要 37 分钟。

委托(Delegate)就是把方法(方法名)作为方法的参数,例如: 

using System;using System.Collections.Generic;using System.Text;namespace TestDemo{    public delegate void Delegate(int arg);    class Program    {        private static void FunctionX2(int x)        {            Console.WriteLine(x*x);        }        private static void FunctionX3(int x)        {            Console.WriteLine(x*x*x);        }        private static void Action(int x, Delegate function)        {            function(x);        }        static void Main(string[] args)        {            Action(2, FunctionX2);            Action(2, FunctionX3);            Console.ReadKey();        }    }}

委托可以简化代码,但是更大的意义是在一个线程中调用另一个线程的代码,先来看一个程序。

using System;using System.Collections.Generic;using System.ComponentModel;using System.Data;using System.Drawing;using System.Linq;using System.Text;using System.Windows.Forms;namespace WinFormTest{    public partial class MainForm : Form    {        public MainForm()        {            InitializeComponent();        }        private void Print(int n)        {            for (int i = 1; i <= n; i++)            {                Output.AppendText(i.ToString() + Environment.NewLine);            }        }        private void Show_Click(object sender, EventArgs e)        {            Show.Enabled = false;            Output.Text = "";            int n = int.Parse(Input.Text);            Print(n);            Show.Enabled = true;        }    }}

当输入100的时候,显示框能迅速显示,1000的时候显示开始出现停顿,10000的时候,主窗口明显会卡住,直到输出完成。怎么样让界面不被卡住呢?答案就是用多线程。

以下就是经过多线程改进的代码。 

using System;using System.Collections.Generic;using System.ComponentModel;using System.Data;using System.Drawing;using System.Linq;using System.Text;using System.Windows.Forms;using System.Threading;namespace WinFormTest{    public partial class MainForm : Form    {        private int n;                public MainForm()        {            InitializeComponent();        }        private void Print()        {            for (int i = 1; i <= n; i++)            {                Output.AppendText(i.ToString() + Environment.NewLine);            }        }        private void Show_Click(object sender, EventArgs e)        {            Show.Enabled = false;            Output.Text = "";            n = int.Parse(Input.Text);            new Thread(new ThreadStart(Print)).Start();            Show.Enabled = true;        }    }}

运行时出现如下错误

在子线程中无法访问UI线程的对象,这个时候代理就该出场了。以下是用代理实现后的代码 

using System;using System.Collections.Generic;using System.ComponentModel;using System.Data;using System.Drawing;using System.Linq;using System.Text;using System.Windows.Forms;using System.Threading;namespace WinFormTest{    public partial class MainForm : Form    {        private delegate void UiAction(string text);        private int n;        public MainForm()        {            InitializeComponent();        }        private void Print()        {            UiAction uiAction = new UiAction(AppendText);            for (int i = 1; i <= n; i++)            {                Output.Invoke(uiAction, i.ToString() + Environment.NewLine);            }        }        private void AppendText(string text)        {            Output.AppendText(text);        }        private void Show_Click(object sender, EventArgs e)        {            Show.Enabled = false;            Output.Text = "";            n = int.Parse(Input.Text);            new Thread(new ThreadStart(Print)).Start();            Show.Enabled = true;        }    }}

运行之后,即使是10000,Output的Text在不停的变化,主界面仍然处于活动状态,可以拖动或执行其他操作。再来看一下代码的另一种形式 

using System;using System.Collections.Generic;using System.ComponentModel;using System.Data;using System.Drawing;using System.Linq;using System.Text;using System.Windows.Forms;using System.Threading;namespace WinFormTest{    public partial class MainForm : Form    {        private delegate void UiAction(string text);        private int n;        public MainForm()        {            InitializeComponent();        }        private void Print()        {            UiAction uiAction = new UiAction(delegate(string text) { Output.AppendText(text); });            for (int i = 1; i <= n; i++)            {                Output.Invoke(uiAction, i.ToString() + Environment.NewLine);            }        }        private void Show_Click(object sender, EventArgs e)        {            Show.Enabled = false;            Output.Text = "";            n = int.Parse(Input.Text);            new Thread(new ThreadStart(Print)).Start();            Show.Enabled = true;        }    }}

执行正常,这是匿名委托的写法,匿名委托还可写成这样 

using System;using System.Collections.Generic;using System.ComponentModel;using System.Data;using System.Drawing;using System.Linq;using System.Text;using System.Windows.Forms;using System.Threading;namespace WinFormTest{    public partial class MainForm : Form    {        private delegate void UiAction();        private int n;        public MainForm()        {            InitializeComponent();        }        private void Print()        {            for (int i = 1; i <= n; i++)            {                Output.Invoke(new UiAction(delegate() { Output.AppendText(i.ToString() + Environment.NewLine); }));            }        }        private void Show_Click(object sender, EventArgs e)        {            Show.Enabled = false;            Output.Text = "";            n = int.Parse(Input.Text);            new Thread(new ThreadStart(Print)).Start();            Show.Enabled = true;        }    }}

现在我们再来引入一个概念Action,先看代码

using System;using System.Collections.Generic;using System.ComponentModel;using System.Data;using System.Drawing;using System.Linq;using System.Text;using System.Windows.Forms;using System.Threading;namespace WinFormTest{    public partial class MainForm : Form    {        private int n;        public MainForm()        {            InitializeComponent();        }        private void Print()        {            for (int i = 1; i <= n; i++)            {                Action
action = AppendText; Output.Invoke(action, i.ToString() + Environment.NewLine); } } private void AppendText(string text) { Output.AppendText(text); } private void Show_Click(object sender, EventArgs e) { Show.Enabled = false; Output.Text = ""; n = int.Parse(Input.Text); new Thread(new ThreadStart(Print)).Start(); Show.Enabled = true; } }}

Action其实就是委托,Action不带返回,但是可以带参数(形如Action,Action<T>,Action<T1,T2>,Action<T1,T2,T3>,Action<T1,T2,T3,T4>),如果用Lambda表达式来写的话代码就应该是这样

using System;using System.Collections.Generic;using System.ComponentModel;using System.Data;using System.Drawing;using System.Linq;using System.Text;using System.Windows.Forms;using System.Threading;namespace WinFormTest{    public partial class MainForm : Form    {        private int n;        public MainForm()        {            InitializeComponent();        }        private void Print()        {            for (int i = 1; i <= n; i++)            {                Output.Invoke(new Action
((string text) => Output.AppendText(text)), i.ToString() + Environment.NewLine); } } private void Show_Click(object sender, EventArgs e) { Show.Enabled = false; Output.Text = ""; n = int.Parse(Input.Text); new Thread(new ThreadStart(Print)).Start(); Show.Enabled = true; } }}

也可以写成这样的无参形式

using System;using System.Collections.Generic;using System.ComponentModel;using System.Data;using System.Drawing;using System.Linq;using System.Text;using System.Windows.Forms;using System.Threading;namespace WinFormTest{    public partial class MainForm : Form    {        private int n;        public MainForm()        {            InitializeComponent();        }        private void Print()        {            for (int i = 1; i <= n; i++)            {                Output.Invoke(new Action(() => Output.AppendText(i.ToString() + Environment.NewLine)));            }        }        private void Show_Click(object sender, EventArgs e)        {            Show.Enabled = false;            Output.Text = "";            n = int.Parse(Input.Text);            new Thread(new ThreadStart(Print)).Start();            Show.Enabled = true;        }    }}

如果把线程代码也用Lambda形式表达,代码应为这样

using System;using System.Collections.Generic;using System.ComponentModel;using System.Data;using System.Drawing;using System.Linq;using System.Text;using System.Windows.Forms;using System.Threading;namespace WinFormTest{    public partial class MainForm : Form    {        public MainForm()        {            InitializeComponent();        }        private void Show_Click(object sender, EventArgs e)        {            Show.Enabled = false;            Output.Text = "";            new Thread(() =>{                for (int i = 1; i <= int.Parse(Input.Text); i++)                {                    Output.Invoke(new Action(() => Output.AppendText(i.ToString() + Environment.NewLine)));                }            }).Start();            Show.Enabled = true;        }    }}

相比上一种形式,上面这段代码连参数n都省略了,个人认为,Action配上Lambda可以巧妙的把一段实际执行的代码作为类似‘参数’的形式直接执行,这里还稍微引述一个问多线程的问题,如果代码写成这样

using System;using System.Collections.Generic;using System.ComponentModel;using System.Data;using System.Drawing;using System.Linq;using System.Text;using System.Windows.Forms;using System.Threading;namespace WinFormTest{    public partial class MainForm : Form    {        public MainForm()        {            InitializeComponent();        }        private void Show_Click(object sender, EventArgs e)        {            Show.Enabled = false;            Output.Text = "";            new Thread(() =>{                Output.Invoke(new Action(() => {                    for (int i = 1; i <= int.Parse(Input.Text); i++)                    {                        Output.AppendText(i.ToString() + Environment.NewLine);                    }                }));            }).Start();            Show.Enabled = true;        }    }}

执行结果会是主界面会卡住,原因就是‘10000次操作’作为线程的‘1次操作’在主界面线程上执行了,而invoke到主界面线程执行的时候是会占用主线程的执行时间的,这样的写法跟没有用线程差不多,小区别就是用线程的时候Show.Enabled = true代码能马上执行。

Func跟Action类似,不过Func可以带返回,如

using System;using System.Collections.Generic;using System.ComponentModel;using System.Data;using System.Drawing;using System.Linq;using System.Text;using System.Windows.Forms;using System.Threading;namespace WinFormTest{    public partial class MainForm : Form    {        public MainForm()        {            InitializeComponent();        }        private void Show_Click(object sender, EventArgs e)        {            Output.AppendText(DoSomething(new Func
((int n) => n * n))); Output.AppendText(DoSomething(new Func
((int n) => n * n * n))); } private string DoSomething(Func
func) { int n = int.Parse(Input.Text); if (n % 2 == 0) { return "您输入的是偶数,执行结果为:" + func(n) + Environment.NewLine; } else { return "您输入的是奇数,执行结果为:" + func(n) + Environment.NewLine; } } }}

 

 

 

 

转载于:https://www.cnblogs.com/bady1211/archive/2012/09/27/2706101.html

你可能感兴趣的文章
三个 CSS 预处理器(框架):Sass、LESS 和 Stylus
查看>>
【转】QT中QWidget、QDialog及QMainWindow的区别
查看>>
Azure Storage (26) HTML5播放Azure Storage MP4问题
查看>>
收集常用的正则表达式
查看>>
C++ 术语(C++ Primer)
查看>>
otl插入数据不成功
查看>>
查询数据库中满足条件的特定行数据
查看>>
C#编写简单的聊天程序
查看>>
Timus1132(二次剩余方程求解)
查看>>
实战数据结构(5)_双向循环链表的基本操作
查看>>
MyISAM表杂记实验
查看>>
SVN使用
查看>>
【心得】create a data table in webMatrix is very easy!
查看>>
bat 批处理命令 文件 类型 语法 格式 应用 详解
查看>>
Linux(Fedora)下python “no module named numpy” 解决方案
查看>>
[AWS vs Azure] 云计算里AWS和Azure的探究(2.1)
查看>>
31对象的序列化和反序列化
查看>>
Postgres远程访问配置
查看>>
C#各种泛型集合体验
查看>>
Swift 2.x 升为 swift 3后语法不兼容问题适配
查看>>