• winform应用程序:非控件创建线程无法操作控件


    在winform中常常会有耗时的操作,需要有进度条来与用户进行交互,告诉用户当前操作的进度状况。

    在这种情况下,为避免耗时操作阻塞UI主线程,会为操作单独开一个工作线程。但是当工作线程去更新Form上的ProgressBar的进度时,异常抛出了:线程间操作无效: 从不是创建控件“progressBarUpdate”的线程访问它。

    这是因为progressBarUpdate这个控件是由UI主线程创建并维护的,而工作线程直接去操作UI线程创建的控件显然是不被允许的,但是工作线程确实需要通知progressBarUpdate去更新状态,如何解决这个问题呢?

    我们可以使用Control 中的方法  public IAsyncResult BeginInvoke(Delegate method, params object[] args) 来优雅的解决。

    public partial class frmProduct : Form
        {
            public frmProduct()
            {
                InitializeComponent();
            }
    
            public delegate void WorkDelegate();
    
            private void button1_Click(object sender, EventArgs e)
            {
                var workThread = new Thread(new ThreadStart(DoSomeLongTermWork));
                workThread.Start();
            }
    
            private void DoSomeLongTermWork()
            {
                for (int i = 0; i <= 100; i++)
                {
                    Thread.Sleep(100);
    
                    UpdateProgressStatus(i);
                }
            }
    
            public delegate void  UpdateProgressDelegate(int progress);
    
            public void UpdateProgressStatus(int progress)
            {
                if(this.InvokeRequired)
                {
                    this.BeginInvoke(new UpdateProgressDelegate(UpdateProgressStatus),progress);
                    return;
                }
                progressBarUpdate.Value = progress;
            }
    
            private void button2_Click(object sender, EventArgs e)
            {
                MessageBox.Show("the main ui thread is blocked!");
            }
        }

    其中 this.InvokeRequired 是Control的一个属性,它会去比较当前线程是否是winform主线程,是返回false,不需要invoke,可以直接操作control,不是则需要调用this.BeginInvoke(Delegate,parms object[] args)将更新control的操作转到winform主线程中进行。

    [SRDescription("ControlInvokeRequiredDescr")]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        [Browsable(false)]
        [EditorBrowsable(EditorBrowsableState.Advanced)]
        public bool InvokeRequired
        {
          get
          {
            using (new Control.MultithreadSafeCallScope())
            {
              HandleRef hWnd;
              if (this.IsHandleCreated)
              {
                hWnd = new HandleRef((object) this, this.Handle);
              }
              else
              {
                Control marshalingControl = this.FindMarshalingControl();
                if (!marshalingControl.IsHandleCreated)
                  return false;
                hWnd = new HandleRef((object) marshalingControl, marshalingControl.Handle);
              }
              int lpdwProcessId;
              return System.Windows.Forms.SafeNativeMethods.GetWindowThreadProcessId(hWnd, out lpdwProcessId) != System.Windows.Forms.SafeNativeMethods.GetCurrentThreadId();
            }
          }
        }
  • 相关阅读:
    Python 学习笔记 -- 列表的基本使用
    帮助你构建云服务的开源平台:openstack
    一个基于Asterisk构建的VOIP应用软件:Elastix介绍
    Asterisk项目概述
    Asterisk 代码架构概述
    云计算投入成本分析
    撕去服务器虚拟化和云计算的神秘面纱
    VOIP开源项目源码地址
    websocket技术
    JSP页面静态化总结之一使用URLRewrite实现url地址伪静态化
  • 原文地址:https://www.cnblogs.com/philzhou/p/2542984.html
Copyright © 2020-2023  润新知