代码之家  ›  专栏  ›  技术社区  ›  Armbrat

跨线程UI组件调用

  •  3
  • Armbrat  · 技术社区  · 17 年前

    namespace MyApplication.Components
    {
        using System.Windows.Forms;
    
        /// <summary>
        /// Thread-safe implementation of the DevExpress.XtraEditors.ComboBoxEdit class.
        /// </summary>
        public class ComboBoxEditThreadSafe : DevExpress.XtraEditors.ComboBoxEdit
        {
            /// <summary>
            /// Gets or sets the edit value.
            /// </summary>
            /// <value>The edit value.</value>
            public override object EditValue
            {
                get
                {
                    return base.EditValue;
                }
    
                set
                {
                    if (this.InvokeRequired)
                    {
                        this.Invoke(new MethodInvoker(delegate
                        {
                            this.SetEditValue(value);
                        }));
                    }
                    else
                    {
                        this.SetEditValue(value);
                    }
                }
            }
    
            /// <summary>
            /// Sets the edit value.
            /// </summary>
            /// <param name="value">The value.</param>
            private void SetEditValue(object value)
            {
                base.EditValue = value;
            }
        }
    }
    
    4 回复  |  直到 17 年前
        1
  •  2
  •   Charles Bretana    17 年前

    您还可以委托给另一个执行该工作的方法,在该方法中,如果在错误的线程上,(BeginInvoke返回true),则再次调用相同的方法。这样做可以消除重复代码的需要。

    public class ComboBoxEditThreadSafe : DevExpress.XtraEditors.ComboBoxEdit    
    {       
       public override object EditValue        
       {            
           get            
           {                             
                return base.EditValue;            
           }            
           set  
           {                
             SetValue(value);
           }
       }
    
    
    
        private void delegate SetValueDlg(object valeu);
        private void SetValue(object value)
        {
            if (this.InvokeRequired)
                 this.BeginInvoke(
                     (SetValueDlg)SetValue,  // calls itself, but on correct thread
                     new object[] { value });
            else
    
                  base.editValue = value;  
    
        }
    }
    

    您还可以使用Action()泛型类来消除创建显式委托类的需要。。。

       public class ComboBoxEditThreadSafe : DevExpress.XtraEditors.ComboBoxEdit    
    {       
       public override object EditValue        
       {            
           get {  return base.EditValue;   }            
           set { SetValue(value); }
       }
    
       private void SetValue(object value)
       {
           if (this.InvokeRequired)
               this.BeginInvoke(
                   new Action<object>(SetValue),  // calls itself, but on correct thread
                   new object[] { value });
           else                
                  base.editValue = value;  
    
       }
    

    }

        2
  •  1
  •   FacticiusVir    17 年前

    是的,这是invokererequired&的正确用法;调用,但我建议创建一个单独的、特定于目的的、线程安全的属性,并将其作为广告发布。

        3
  •  0
  •   M1EK    17 年前

    我的UI方法与您的类似:

    public void setStatusLabelText(String s)
        {
            if (footerStatusLabel.InvokeRequired) {
                StringUpdateInvokeDelegate callback = new StringUpdateInvokeDelegate(setStatusLabelText);
                this.Invoke(callback, new object[] { s });
            }
            else {
                this.footerStatusLabel.Text = s;
            }            
        }
    

    (这对于.net来说可能已经过时了——但关键是,如果你已经在正确的线程上,你可以在这个方法中进行操作——这样读起来就不那么烦人了,但与Java、IMO相比仍然很烦人)。

        4
  •  0
  •   Community Mohan Dere    9 年前

    我会把我的2美分注射到这里。对invokererequired/BeginInvoke/Invoke的实际调用不是完全线程安全的。(见 Avoiding the woes of Invoke/BeginInvoke in cross-thread WinForm event handling?