目录
委托相关
对于委托,我们都知道他是一个引用类型,具有引用类型所具有的通性。需要知道的是它保存的不是实际值,只是是保存对存储在托管堆中的对象的引用。或说的直接点,委托就相当于叫人帮忙,让它帮你做一些事情。我这里就举一些委托操作的小实例,来简单的说一下。
在开始举例之前,再说一下,委托一般包含三个方法,分别是BeginInvoke、EndInvoke、Invoke。EndInvoke就不必说了,一看就知道是干嘛的。Invoke 和BeginInvoke,前一个是同步委托,后一个是异步委托,何为同步,何为异步呢?其实也可从字面意思理解,同步就是同时进行的,不能说你先执行,我后执行,那么异步就是与同步相对的,但是也不全相对,因为异步的执行不受主进程的影响,执行全看它个人了。
这里所说的委托都是自己新建的委托,但还有种委托,是C#控件自带的委托,也分有同步异步之分,控件委托用处很大,在后面说线程的时候会说到,因为在使用线程时,有时控件委托是必要的。
下面先单独说一个委托的例子吧:
第一步:创建委托
//创建委托
[Serializable, ComVisible(true)]//可省略
public delegate void testDelegate(object sender, EventArgs e);
第二步:定义委托API
public class DelegateApi
{
//定义委托API
public static event testDelegate TestClick;
//委托实现方法
public static void OnTest(object sender, EventArgs e)
{
testDelegate handler = TestClick;
if (handler != null)
handler(sender, e);
}
}
第三步:调用委托
//同类调用委托API
OnTest(sender, e);
//非同类调用委托API
DelegateApi.OnTest(sender, e);
第四步:其他窗体实现委托
private void Form1_Load(object serder, EventArgs e)
{
//实例化API方法调用
DelegateApi.TestClick += Form1_TestClick;
}
private void Form1_TestClick(object sender, EventArgs e)
{
MessageBox.Show("委托调用");
}
这是委托最常用也是很实用的一个例子,我们可以通过这种方式,实现不同窗体之间的交互,比如在A窗体调用委托API,在B窗口实例化API方法,这样就能达到在A窗口控制B窗口方法的执行。那么你可能就会问,我想传参数怎么办,其实很简单,委托API的传参与普通方法的传参类似,只需要在定义委托和API时这样定义:
补充
这里的handler其实类似于 handler.Invoke();,也就是同步委托,调用即执行。那么异步委托只需要写成handler.BeginInvoke(null, null);,这是没有回调函数的异步委托,当然想要调用回调函数,只需如下编写:
控件创建委托
Control的Invoke和BeginInvoke都执行在主线程即UI线程上
创建异步委托
private delegate void BeginInvokeDelegate();
private void BeginInvokeMethod(){
//C代码段
}
private void butBeginInvoke_Click(object sender, EventArgs e) {
//A代码段.......
this.BeginInvoke(new BeginInvokeDelegate(BeginInvokeMethod));
//B代码段......
}
(1)A在UI线程上执行完后,开始BeginInvoke,BeginInvoke是异步
(2)InvokeMethod方法,即代码段C不会执行,而是立即在UI线程上执行代码段B。
(3)代码段B执行完后(就是说butBeginInvoke_Click方法执行完后),InvokeMethod方法,即代码段C才在UI线程上继续执行。
Thread调用Control的Invoke
private Thread invokeThread;
private delegate void invokeDelegate();
private void StartMethod(){
//C代码段......
Control.Invoke(new invokeDelegate(invokeMethod));
//D代码段......
}
private void invokeMethod(){
//E代码段
}
private void butInvoke_Click(object sender, EventArgs e) {
//A代码段.......
invokeThread = new Thread(new ThreadStart(StartMethod));
invokeThread.Start();
//B代码段......
}
1. UI执行A
2. UI开线程InvokeThread,B和C同时执行,B执行在线程UI上,C执行在线程invokeThread上。
3. invokeThread封送消息给UI,然后自己等待,UI处理完消息后,处理invokeThread封送的消息,即代码段E
4. UI执行完E后,转到线程invokeThread上,invokeThread线程执行代码段D
Thread调用Control的BeginInvoke
private Thread beginInvokeThread;
private delegate void beginInvokeDelegate();
private void StartMethod(){
//C代码段......
Control.BeginInvoke(new beginInvokeDelegate(beginInvokeMethod));
//D代码段......
}
private void beginInvokeMethod(){
//E代码段
}
private void butBeginInvoke_Click(object sender, EventArgs e) {
//A代码段.......
beginInvokeThread = new Thread(new ThreadStart(StartMethod));
beginInvokeThread .Start();
//B代码段......
}
1. UI执行A
2. UI开线程beginInvokeThread,B和C同时执行,B执行在线程UI上,C执行在线程beginInvokeThread上。
3. beginInvokeThread封送消息给UI,然后自己继续执行代码D,UI处理完消息后,处理invokeThread封送的消息,即代码段E
拓展
委托实现异步线程,也可理解为非UI异步线程,为啥要我要说可以理解为非UI异步线程呢,因为它的委托创建与UI没有直接关系
#region 非UI异步线程
private object _args;
public delegate void RunHandler(object args);//事件处理委托
private event RunHandler Runs;//委托事件
private event RunHandler CallBackFun;//委托事件
public delegate void CallBackDelegate(RunHandler handler, object args);
CallBackDelegate _d = TakesAWhile;
/// <summary>
/// 执行入口
/// </summary>
/// <param name="run"></param>
/// <param name="callBackFun"></param>
/// <param name="args"></param>
public void DoProcess(RunHandler run, RunHandler callBackFun, object args)
{
Runs = run;
_args = args;
CallBackFun = callBackFun;
//创建有回调函数的异步线程
_d.BeginInvoke(Runs, _args, CallBack, _d);
//创建无回调函数的异步线程
//_d.BeginInvoke(Run, _args, null, null);
}
/// <summary>
/// 定义委托引用的方法
/// </summary>
/// <param name="handler"></param>
/// <param name="args"></param>
private static void TakesAWhile(RunHandler handler, object args)
{
if (handler != null)
{
RunHandler invoke = handler;
invoke(args);
}
}
/// <summary>
/// 定义委托调用完毕后回调函数
/// </summary>
/// <param name="ar"></param>
private void CallBack(IAsyncResult ar)
{
if (ar == null)
{
throw new ArgumentException("ar");
}
CallBackDelegate id = ar.AsyncState as CallBackDelegate;
id.EndInvoke(ar);
if (CallBackFun != null)
{
RunHandler invoke = CallBackFun;
invoke(_args);
}
}
#endregion
这里只对委托使用做了一部分举例,更多的用法,大家可以多多实践,去发现新大陆,我这里就先不去发现了,因为接下来准备谈一下线程。