0


C# winform delegate委托以及异步调用委托(跨线程调用控件UI)使用总结

文章目录

前言

为啥写这个?
因为本人间断性的会进行winform的开发, 对各种跨线程的处理,以及UI的处理.每次都忘记怎么写.都要重新百度,效率很低.
这里记录总结一下.也分项给有需要的朋友 哈哈哈

几个概念

什么是委托delegate

刚开始接触的时候,觉得太TM绕了(我智商低).自己总结一下. 委托就是一个方法行为的集合 , 执行委托 就相当于执行一些列的行为
一个委托可以只有一个方法,可以一个方法都没有,也可以有N个方法
说人话就是 ,委托就是一个代理委托人,我把要执行的任务事情(function)告诉他,他收集好之后,等待我的命令,我让他执行,他就把事情都给我办了.

为什么要委托

  1. 可以解耦. 只要参数类型一致的方法,都可以塞进一个委托里面.那么在开发者A的角度.我只要执行这个委托就可以了. 具体这个委托要做的动作细节,开发者B自己去实现
  2. 跨线程UI操作.这个是我用得最多的. 界面卡死,无响应,报错等等,大部分和UI进程阻塞有关. 合理的方法应该是:- 主线程就负责UI界面的调度.- 涉及到耗时的动作,全部扔给线程去异步处理.- 处理完成后,通过invoke委托的方法,来触发UI刷新(因为子线程invoke只能是委托,所以要用委托. 是吗? 我也不确定,哈哈)
  3. 其他应该还有点别的用处,但是我用不上

直接上代码例子

直接来个最简单的写法

这个目前我认为最简单而已,仅仅是我认为.
即通过lamda表达式 和thread 来实现委托异步回调

//定义委托 作用:回调主界面UIdelegatevoidDelegateHandleUI(String str);privatevoidbtn_Getversion_threadlamda_Click(object sender,EventArgs e){//声明一个线程异步执行Thread t1 =newThread(delegate(){//线程里面执行 耗时的动作JObject jo =getVersion();//耗时动作结束后  通过lamda表达式 直接写逻辑invoke 委托,执行页面UI刷新方法    ;this.Invoke(newDelegateHandleUI((a)=>{
                    textBox1.Text = a;}),newObject[]{ jo.ToString()});});//执行这个线程
            t1.Start();}

这里没有额外声明函数,直接通过lamda去定义了一个委托动作来实现.

稍微复杂完整的写法

//定义委托 作用:回调主界面UIdelegatevoidDelegateHandleUI(String str);privatevoidbtn_Getversion_thread_Click(object sender,EventArgs e){//告诉委托 要委托执行哪个方法DelegateHandleUI delegateHandleUI = UIshow;//声明一个线程异步执行Thread t1 =newThread(delegate(){//线程里面执行 耗时的动作JObject jo =getVersion();//耗时动作结束后  invoke 委托,执行页面UI刷新方法    ;this.Invoke(delegateHandleUI,newObject[]{ jo.ToString()});//delegateHandleUI("888"); 直接这样写 会报 跨线程调用ui控件错误  需要通过上面的 invoke的方式取回调委托});
            t1.Start();}publicvoidUIshow(String str){
            textBox1.Text = str;}

这里相比上面, 多了一个 预先定义方法,然后将方法绑定到委托的动作
好处是可以类似这样

DelegateHandleUI delegateHandleUI += UIshow1;
DelegateHandleUI delegateHandleUI += UIshow2;

同时塞入多个方法给一个委托. 让委托一次执行多个动作

来个Action的写法

publicpartialclassForm1:Form{delegatevoidDelegateHandleUI(String str);publicForm1(){InitializeComponent();}publicvoidUIshow(String str){
            textBox1.Text = str;}/// <summary>/// 这里只是回调 ,一般不同个这里的      IAsyncResult ar 来处理控件/// 这里仍然是线程的方法/// </summary>/// <param name="ar"></param>privatevoidMyAsynCallback(IAsyncResult ar){// 这时候的ar.AsyncState 就是 "123"          //textBox1.Text = ar.AsyncState.ToString(); 注意这里仍然是 线程的动作.调用控件会犯法
            Console.WriteLine("异步调用结束");// Console.ReadLine();}privatevoidbtn_Getversion_Click(object sender,EventArgs e){Action action =(()=>{#region 需要等待的硬件调用object obj = SiReader.getVerion();JObject jo = JObject.FromObject(obj);#endregion#region 通过委托方法 刷新主线程UIDelegateHandleUI delegateHandleUI =newDelegateHandleUI(UIshow);this.Invoke(delegateHandleUI,newobject[]{ jo.ToString()});#endregion});//必须定义一个AsyncCallback  哪怕不处理任何动作AsyncCallback asyncCallBack =newAsyncCallback(MyAsynCallback);#region 异步执行action 
            action.BeginInvoke(asyncCallBack,"123");//这里传123 就是看看MyAsynCallback的  ar.AsyncState 能不能获取到123#endregion#region 以下3个写法 等效, 属于同步 不是异步!!//this.BeginInvoke(action);  //这样是同步 不是异步!!//this.Invoke(action);//action();#endregion}}

这个稍微麻烦的就是需要实现一个AsyncCallback 方法才能实现异步
有强迫的朋友就别用了

来个Action带入参的写法

privatevoidbtn_Getversion_Click(object sender,EventArgs e){//Action action = (() =>Action<int,int> action =((a,b)=>{#region 需要等待的硬件调用 JObject jo =getVersion();#endregion
                                       Console.WriteLine("测试Action 传参数:"+(a + b).ToString());#region 通过委托方法 刷新主线程UIDelegateHandleUI delegateHandleUI =newDelegateHandleUI(UIshow);this.Invoke(delegateHandleUI,newobject[]{ jo.ToString()});#endregion});//必须定义一个AsyncCallback  哪怕不处理任何动作AsyncCallback asyncCallBack =newAsyncCallback(MyAsynCallback);#region 异步执行action //后面两个参数固定, 第一个 和 第二个 参数为 定义Aciton时候的入参
            action.BeginInvoke(3,4,asyncCallBack,"123");//这里传123 就是看看MyAsynCallback的  ar.AsyncState#endregion#region 以下3个写法 等效, 属于同步 不是异步!!//this.BeginInvoke(action);  //这样是同步 不是异步!!//this.Invoke(action);//action();#endregion}

类似还有Func的写法,这个和Action类似,只是多了返回值而已,不记录了

标签: ui c# 开发语言

本文转载自: https://blog.csdn.net/gxlzhhx/article/details/128568462
版权归原作者 何浩翔 所有, 如有侵权,请联系我们删除。

“C# winform delegate委托以及异步调用委托(跨线程调用控件UI)使用总结”的评论:

还没有评论