C# 委托 、事件、同步、异步知识点归纳
2020-12-24 17:26
标签:div log 使用 结果 自定义事件 任务 mouse 定义 类的构造函数 一、委托 基本用法: 1.声明一个委托类型。委托就像是‘类‘一样,声明了一种委托之后就可以创建多个具有此种特征的委托。(特征,指的是返回值、参数类型) 2.创建一个在1中创建的委托类型的委托。 3.为2中创建的具体的委托添加响应函数。响应函数必须符合1中的‘特征‘。 4.完成以上三步之后,就可以使用Invoke来对委托进行调用了。Invoke可以选择调用的目标函数,调用优先级,以及调用的参数。 上面是基本用法,除了这种基本用法之外,还可以结合var、匿名委托、lambda委托等方法。 完整代码: 委托的用处: 委托的优点,是可以实现异步(BeginInvoke),还可以在某种需要同时调用多个同参数、返回值的情况下简化代码。 二、事件 基本用法: 1.定义委托。 2.定义事件。 3.为事件添加响应函数。 4.为事件规定触发(调用)方式。(【也可以没有触发方式,直接invoke】) 解说: C#里,每一种‘事件Event‘大概都对应着其‘事件处理者EventHandler‘。比如Process类的OutputDataReceived事件对应着DataReceivedEventHandler,对于非特异性的‘事件‘,比如PasswordChanged 这种,它们统一都对应着RoutedEventHandler或者EventHandler这种较为通用的‘事件处理者‘。然而,‘EventHandler‘也只是充当了一个中介的角色,真正触发了‘Event‘之后要做什么,还需要我们手动指定,像这样: EventHandler本来也是委托。比如 自定义事件 自定义事件是一种类似于委托的方式, 自定义事件某种意义上改变了程序的流程,使得某个条件的变化由‘不断查询‘转变为‘订阅与处理‘的关系。 自定义事件需要有以下几个元素: 事件的发起者,事件的订阅,以及事件的处理程序。从发起者到处理程序之间是可以传参数的。 一个事件的‘发起‘可以依赖于某种系统消息,比如‘OnKeyDown‘、‘OnMouseClick‘(【我目前还没见过这么写的源码】),也可以在某个条件达成时(比如两次输入了同样的字符)自行调用(其实收到系统消息也算是‘条件达成‘)。【更多的event是这么写出来的】 有些事件,并没有明显的‘发起者‘。 委托和事件是啥关系 委托和自定义事件的使用方式十分十分类似。event 只有类的内部可以 Invoke,delegate的话,在哪都可以Invoke。调用的方式貌似也略有区别(传参方式) 由于调用方式和传参的差异,event显得更保守/稳定一些。event也更容易从‘理解‘上更容易接受。 delegate貌似更多的用于进行异步(begin invoke)。而event则更多的用来做自定义事件。 委托和异步是啥关系 异步是委托可以实现的一种功能(或者叫做‘现象‘也可以) 异步可以由很多种其他方式体现,比如多线程(thread,threadpool,task等等)。 .Net的委托本质上就是指向函数的指针,只不过这种指针是经过封装后类型安全的。委托和线程是两个不同的概念,线程是动态的,委托就是一个或一组内存地址,是静态的。线程执行时如果遇到了指向函数的指针就执行这个函数。 使用BeginInvoke调用委托方法,其结果和调用一个新线程一样。多线程编程在开发中经常用到,比如将后台计算和UI更新主线程分离,防止界面卡顿等,着重关注线程池ThreadPool,因为Task任务就是整理了它。 .NET 4包含新名称空间System.Threading.Tasks,它 包含的类抽象出了线程功能。Task 在后台使用ThreadPool。 任务表示应完成的某个单元的工作。 这个单元的工作可以在单独的线程中运行,也可以以同步方式启动一个任务,这需要等待主调线程。 使用任务不仅可以获得一个抽象层,还可以对底层线程进行很多控制。 在安排需要完成的工作时,任务提供了非常大的灵活性。 例如,可以定义连续的工作—— 在一个任务完成后该执行什么工作。 这可以区分任务成功与否。 另外,还可以在层次结构中安排任务。例如,父任务可以创建新的子任务。 这可以创建一种依赖关系,这样,取消父任务,也会取消其子任务。 要启动任务,可 以使用 TaskFactory类 或 Task类 的构造函数和 Start()方法。Task类的构造函数在创建任务上提供的灵活性较大。 在上面的代码中,可 以看到启动新任务的不同方式。第一种方式 使用实例化TaskFactory类 ,在其中把 TaskMedlod()方 法传递给StartNew()方法,就会立即启动任务。 第二种方式使用 Task类的构造函数。 实例化 Task对象时,任务不会立即运行,而是指定 Created状态。接着调用 Task类的Start()方法,来启动任务。 使用Task类 时,除了调用 Start()方法,还可以调用RunSynchronously()方法。这样,任务也会启动,但在调用者的当前线程中它正在运行,调用者需要一直等待到该任务结束。 默认情况下,任务是异步运行的。 使用Task类的构造函数和TaskFactory类的StartNew()方法时,都可以传递TaskCreationOptions枚举中的值。设置LongRunning选项,可以通知任务调度器,该任务需要较长时间执行,这样调度器更可能使用新线程。如果该任务应关联到父任务上,而父任务取消了,则该任务也应取消,此时应设置 AuachToParent选项。PreferFairness的值表示,调度器应提取出已在等待的第一个任务。 如果一个任务在另一个任务内部创建,这就不是默认情况 。如果任务使用子任务创建了其他工作,子任务就优先于其他任务。 它们不会排在线程池队列中的最后。 如果这些任务应以公平的方式与所有其他任务一起处理,就设置该选项为PreferFairness。 泛型无返回值委托Action,有返回值Func,虽然使用Delegete委托可以达到同样的效果,但是用Action等泛型委托写法要更简洁。除了Delegate委托我们还可以使用Action public delegate void SomeKindOfDelegate(string result);
public SomeKindOfDelegate aDelegate;
aDelegate +=new SomeKindOfDelegate(aFunctionThatJustForDelegate);
private void aFunctionThatJustForDelegate(string result)
{
MessageBox.Show(result);
}
aDelegate.BeginInvoke("Hello~I‘m being invoked!", null, null);
namespace wtfIsDelegate
{
public delegate void SomeKindOfDelegate(string result);
public partial class Form1 : Form
{
public event SomeKindOfDelegate aDelegate;
public Form1()
{
InitializeComponent();
aDelegate +=new SomeKindOfDelegate(aFunctionThatJustForDelegate);
aDelegate.BeginInvoke("Hello~I‘m being invoked!", null, null);
}
private void btnDelegate_Click(object sender, EventArgs e)
{
}
private void aFunctionThatJustForDelegate(string result)
{
MessageBox.Show(result);
}
}
}
public delegate void SomeKindOfDelegate(string result);
public event SomeKindOfDelegate aDelegate;
process.Exited += new EventHandler(CmdProcess_Exited);
process.Exited += new EventHandler(CmdProcess_Exited); // 注册进程结束事件 。
public delegate void DataReceivedEventHandler(object sender, DataReceivedEventArgs e);
多线程
.Net为了方便编程,给委托赋予了两种方式以供调用线程来执行,即同步和异步方式,它们分别通过Invoke和BeginInvoke来开启。Invoke就是同步执行,由调用线程来执行,而BeginInvoke则开启了一个后台线程来执行delegate所指向的函数,这个后台线程和调用线程之间属于异步执行方式。实际上有了delegate这个概念,你在编程时就可以不用直接使用Thread类来开辟新的线程了,因为微软替你实现了。Task
启动一个Task
在启动任务时,会创建Task类 的一个实例,利用Action或Actionstatic void TaskMethod()
{
Console.WriteLine("running in a task");
Console.WriteLine("Task id: {0}",Task.CurrentId);
}
//using task factory
TaskFactory tf = new TaskFactory();
Task t1 = tf.StartNew(TaskMethod);
//using the task factory via a task
Task t2 = Task.TaskFactory.StartNew(TaskMethod);
//using Task constructor
Task t3 = new Task(TaskMethod);
t3.Start();
Task t4 = new Task(TaskMethod, TaskCreationOptions.PreferFairness);
t4.Start();
Action,Func等委托
泛型Action
Func
下面就直接给一个Actionusing System;
namespace DelegateFuncAction
{
class Program
{
static void Main(string[] args)
{
Func
下一篇:强制卸载win软件
文章标题:C# 委托 、事件、同步、异步知识点归纳
文章链接:http://soscw.com/index.php/essay/37963.html