• 委托与线程的见解(上)——委托


    委托相关

            对于委托,我们都知道他是一个引用类型,具有引用类型所具有的通性。需要知道的是它保存的不是实际值,只是是保存对存储在托管堆中的对象的引用。或说的直接点,委托就相当于叫人帮忙,让你帮你做一些事情。我这里就举一些委托操作的小实例,来简单的说一下。

            在开始举例之前,再说一下,委托一般包含三个方法,分别是BeginInvoke、EndInvoke、Invoke。EndInvoke就不必说了,一看就知道是干嘛的。Invoke 和BeginInvoke,前一个是同步委托,后一个是异步委托,何为同步,何为异步呢?其实也可从字面意思理解,同步就是同时进行的,不能说你先执行,我后执行,那么异步就是与同步相对的,但是也不全相对,因为异步的执行不受主进程的影响,执行全看它个人了。

            这里所说的委托都是自己新建的委托,但还有种委托,是C#控件自带的委托,也分有同步异步之分,控件委托用处很大,在后面说线程的时候会说到,因为在使用线程时,有时控件委托是必要的。

            下面先单独说一个委托的例子吧:

    第一步:

           //创建委托
    private delegate void testDelegate();
    第二步:

    //定义委托API
    private event testDelegate TestClick;
    public void OnTest()
    {
    testDelegate handler = TestClick;
    if (handler != null)
    handler();
    }
    第三步:

    //调用委托API
    OnTest();
    第四步:

    这是委托最常用也是很实用的一个例子,我们可以通过这种方式,实现不同窗体之间的交互,比如在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
    这里只对委托使用做了一部分举例,更多的用法,大家可以多多实践,去发现新大陆,我这里就先不去发现了,因为接下来准备浅谈一下线程。
    ---------------------
    作者:玲妹妹的辉哥哥
    来源:CSDN
    原文:https://blog.csdn.net/qwerdfcv/article/details/80291152
    版权声明:本文为博主原创文章,转载请附上博文链接!



  • 相关阅读:
    深入理解iostat(转载)
    renameat2函数RENAME_EXCHANGE参数使用
    maven相关
    IDEA快捷键
    zookeeper
    SHA1字符串加密 积跬步
    C语言void关键字
    目录项、inode、数据块
    CAD带文字线型的文字偏移bug介绍
    20192419 202120222 《网络与系统攻防技术》实验五实验报告
  • 原文地址:https://www.cnblogs.com/asdyzh/p/9860307.html
Copyright © 2020-2023  润新知