zoukankan      html  css  js  c++  java
  • 实现 winform 异步跨线程访问UI控件

    实现 winform 异步跨线程访问UI控件

     在开发winform时经常会用到多线程防止界面出现假死现象,比如当你单击某个按钮时,需要执行很多代码,但是在执行过程中想实时的将当前执行的情况报告给用户,类型进度条或文本什么的。

    这个时候很显然,如果你把要实现的内容放在按钮方法里时,其实界面要等这个按钮执行完后才能输出来,这个时候就达不到我们的预期了;那么怎么才能解决问题呢。

    我初略终结了一下有以下几种方法:

        1.采用BackgroundWorker控件,这个控件将要实时输出的内容写在事件中;

    复制代码
     1 private void button1_Click(object sender, EventArgs e)
     2         {
     3             //异步执行逻辑
     4             backgroundWorker1.RunWorkerAsync();
     5         }
     6         private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
     7         {
     8             //实现业务逻辑
     9             int i = 5;
    10             i = Math.Abs(i);
    11             //报告当前处理进度
    12             backgroundWorker1.ReportProgress(50);
    13         }
    14 
    15         private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
    16         {
    17             //当前进度
    18             int cuur = e.ProgressPercentage;
    19             //实现跨线程控件的输出
    20             this.label1.Text = cuur.ToString();
    21         }
    22 
    23         private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    24         {
    25             //执行完毕可以报告信息
    26             this.label1.Text = "ok";
    27         }
    复制代码

       2.采用委托的方式实现灵活引用Invoke;

    复制代码
     1         private void button2_Click(object sender, EventArgs e)
     2         {
     3             //异步执行逻辑
     4             Thread thread = new Thread(ThreadFunc);
     5             thread.IsBackground = true;
     6             thread.Start();
     7         }
     8         private void ThreadFunc()
     9         {
    10             //实现业务逻辑
    11             int i = 5;
    12             i = Math.Abs(i);
    13             //报告当前处理进度
    14             SetLabel(i.ToString());
    15         }
    16         //定义委托
    17         delegate void SetLabelHandler(string text);
    18         //实现方法
    19         private void SetLabel(string text)
    20         {
    21             if (InvokeRequired)
    22             {
    23                 Invoke(new SetLabelHandler(SetLabel), text);
    24             }
    25             else
    26             {
    27                 this.label1.Text = text;
    28             }
    29         }
    复制代码

      3.采用Lamada表达式动态实现委托调用。

    复制代码
     1         private void button3_Click(object sender, EventArgs e)
     2         {
     3             //异步执行逻辑
     4             Thread thread = new Thread(Func);
     5             thread.IsBackground = true;
     6             thread.Start();
     7         }
     8         private void Func()
     9         {
    10             //实现业务逻辑
    11             int i = 5;
    12             i = Math.Abs(i);
    13             //报告当前处理进度
    14             AsyncUI(() => { label1.Text = i.ToString(); });
    15         }
    16         public void AsyncUI(Action action)
    17         {
    18             if (InvokeRequired)
    19             {
    20                 Invoke(action);
    21             }
    22             else
    23             {
    24                 action();
    25             }
    26         }
    复制代码

    以上是我总结的三种,至于有没有其他方法,欢迎大家来拍砖,在这里我想推荐的是第三种方法,这个方法最灵活。

    下面来谈谈我对这三种的看法:

    对应第一种方法:使用简单,拖控件就ok,但是对应需要显示更负责的数据时比较麻烦;

    对应第二种方法:可以不用拖控件来自由定制,但是同第一种方法一样,如果需要显示更多控件数据,也要定义很多方法和委托,太冗余累赘;

    对于第三种方法:我个人非常喜欢,代码在需要的时候动态使用,但是我也没有仔细分析该方法的性能问题。

     
     
     
    标签: 异步winformlamadac#
  • 相关阅读:
    html表格,table标签
    2-3VRP的基本配置
    6 sys模块
    3 datetime模块
    2 time模块
    1 模块和包的介绍
    12 函数进阶---生成器
    13 函数进阶---迭代器
    10 函数进阶---闭包
    11 函数进阶---装饰器
  • 原文地址:https://www.cnblogs.com/Leo_wl/p/3068618.html
Copyright © 2011-2022 走看看