Winform程序需要处理耗时操作时,往往需要将耗时操作放入新开的子线程进行处理,在子线程中可能会经常去修改或操作主线程上的控件;
如果直接在子线程中操作控件,会报线程间操作无效等错误,这里提供一个我自己经常使用的跨线程操作方式,代码如下:
//跨线程操作控件 //(将数据全部装填完毕后,在一起放到主界面刷新控件;不要一边装填一边刷新主界面控件,这样依然会导致界面卡顿) public void showMsg(string str) { if (textBox.InvokeRequired) { textBox.Invoke(new Action<string>((s) => { this.textBox.Text = s + "\r\n" + this.textBox.Text; }), str); } else { this.textBox.Text = s + "\r\n" + this.textBox.Text; } }
注意:将数据全部装填完毕后,在一起放到主界面刷新控件;不要一边装填一边刷新主界面控件,这样虽然主界面的窗体还能够移动,依然会导致界面卡顿以及其他控件响应延迟;
比如:在给ListView控件装填数据时,应先循环把数据全部装填在一个新建的ListView对象中,然后将新建的ListView对象中的数据利用上述代码循环拷贝到已有控件中;
以上是自己工作中使用的方法,如果有大神有更好的方法,希望能够回复,非常接受批评与指导!
以下记录一下,参考网上写的一个跨线程操作控件的封装类,具体如下:
主要为3个方法:Invoke,Get,Set;
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Reflection; using System.Threading.Tasks; using System.Windows.Forms; namespace Common { /// <summary> /// 跨线程调用控件帮助类 /// </summary> public class InvokeHelper { #region delegates private delegate object MethodInvoker(Control control, string methodName, params object[] args); private delegate object PropertyGetInvoker(Control control, object noncontrol, string propertyName); private delegate void PropertySetInvoker(Control control, object noncontrol, string propertyName, object value); #endregion #region static methods // helpers private static PropertyInfo GetPropertyInfo(Control control, object noncontrol, string propertyName) { if (control != null && !string.IsNullOrEmpty(propertyName)) { PropertyInfo pi = null; Type t = null; if (noncontrol != null) t = noncontrol.GetType(); else t = control.GetType(); pi = t.GetProperty(propertyName); if (pi == null) throw new InvalidOperationException( string.Format( "Can‘t find property {0} in {1}.", propertyName, t.ToString() )); return pi; } else { throw new ArgumentNullException("Invalid argument."); } } /// <summary> /// 调用主界面控件的某个方法,并返回方法执行结果 /// </summary> /// <param name="control"> 控件 </param> /// <param name="methodName"> 方法名 </param> /// <param name="args"> 参数 </param> /// <returns></returns> public static object Invoke(Control control, string methodName, params object[] args) { if (control != null && !string.IsNullOrEmpty(methodName)) { if (control.InvokeRequired) { return control.Invoke( new MethodInvoker(Invoke), control, methodName, args ); } else { MethodInfo mi = null; if (args != null && args.Length > 0) { Type[] types = new Type[args.Length]; for (int i = 0; i < args.Length; i++) { if (args[i] != null) types[i] = args[i].GetType(); } mi = control.GetType().GetMethod(methodName, types); } else mi = control.GetType().GetMethod(methodName); // check method info you get if (mi != null) return mi.Invoke(control, args); else throw new InvalidOperationException("Invalid method."); } } else { throw new ArgumentNullException("Invalid argument."); } } /// <summary> /// 获取主界面控件的某个属性 /// </summary> /// <param name="control"> 控件 </param> /// <param name="propertyName"> 属性名 </param> /// <returns></returns> public static object Get(Control control, string propertyName) { return Get(control, null, propertyName); } public static object Get(Control control, object noncontrol, string propertyName) { if (control != null && !string.IsNullOrEmpty(propertyName)) { if (control.InvokeRequired) { return control.Invoke(new PropertyGetInvoker(Get), control, noncontrol, propertyName ); } else { PropertyInfo pi = GetPropertyInfo(control, noncontrol, propertyName); object invokee = (noncontrol == null) ? control : noncontrol; if (pi != null) if (pi.CanRead) return pi.GetValue(invokee, null); else throw new FieldAccessException( string.Format( "{0}.{1} is a write-only property.", invokee.GetType().ToString(), propertyName )); return null; } } else { throw new ArgumentNullException("Invalid argument."); } } /// <summary> /// 设置主界面控件的某个属性 /// </summary> /// <param name="control"> 控件 </param> /// <param name="propertyName"> 属性名 </param> /// <param name="value"> 属性值 </param> public static void Set(Control control, string propertyName, object value) { Set(control, null, propertyName, value); } public static void Set(Control control, object noncontrol, string propertyName, object value) { if (control != null && !string.IsNullOrEmpty(propertyName)) { if (control.InvokeRequired) { control.Invoke(new PropertySetInvoker(Set), control, noncontrol, propertyName, value ); } else { PropertyInfo pi = GetPropertyInfo(control, noncontrol, propertyName); object invokee = (noncontrol == null) ? control : noncontrol; if (pi != null) if (pi.CanWrite) pi.SetValue(invokee, value, null); else throw new FieldAccessException( string.Format( "{0}.{1} is a read-only property.", invokee.GetType().ToString(), propertyName )); } } else { throw new ArgumentNullException("Invalid argument."); } } #endregion } }
时间: 2024-10-13 08:54:25