zoukankan      html  css  js  c++  java
  • 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();
            }
          }
        }
  • 相关阅读:
    django模板引擎自定义变量
    Ubuntu系统桌面任务栏和启动器全部消失解决方案
    ubuntu beyond compare到期后续期
    git 分支操作 与 远程新建分支后,本地查看不到
    jmeter 安装
    ubuntu apt-get install 时报错curl : Depends: libcurl4 (= 7.58.0-2ubuntu3.6) but 7.61.0-1ubuntu2 is to be installed或者 vim : Depends: vim-common (= 2:8.0.1453-1ubuntu1) but 2:8.0.1766-1ubuntu1 is to be ins
    【uWSGI】 listen queue of socket (fd: 3) 错误分析
    通过CONN_MAX_AGE优化Django的数据库连接
    Linux(CentOS) 查看当前占用CPU或内存最多的K个进程
    centos django Failed to load resource: net::ERR_INCOMPLETE_CHUNKED_ENCODING
  • 原文地址:https://www.cnblogs.com/philzhou/p/2542984.html
Copyright © 2011-2022 走看看