C# 多线程中更新窗体控件
来源:互联网 发布:模拟炒汇软件 编辑:程序博客网 时间:2024/05/16 16:20
在C#中用到多线程处理一些功能,同时希望界面同步显示更新,如果直接写代码就会出现一些问题:
问题代码:
Thread ScanFileThread;
ScanFileThread = new Thread(WorkScanFileThread);
this.ScanFileThread.Start();
WorkScanFileThread线程体代码:
private void WorkScanFileThread()
{
for (nDriveIndex = 0; nDriveIndex < DriveList.Count; nDriveIndex++)
{
this.listView3.Items[nDriveIndex].SubItems[2].Text = "Scaning...";
...
//指定的操作,操作结束后设置控件文本为完成
...
SetListViewControlPropertyValue(this.listView3, nDriveIndex, 2, "Finished");
}
}
直接这样调用,会在运行时抛出异常,下面是异常信息:
未处理 System.InvalidOperationException
Message="Cross-thread operation not valid: Control 'listView3' accessed from a thread other than the thread it was created on."
Source="System.Windows.Forms"
StackTrace:
at System.Windows.Forms.Control.get_Handle()
at System.Windows.Forms.ListView.ListViewNativeItemCollection.DisplayIndexToID(Int32 displayIndex)
at System.Windows.Forms.ListView.ListViewNativeItemCollection.get_Item(Int32 displayIndex)
at System.Windows.Forms.ListView.ListViewItemCollection.get_Item(Int32 index)
at Undelete_UI.Scan.WorkScanFileThread() in D:\C# Project\Undelete_UI - Copy\Undelete_UI\Scan.cs:line 123
at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
at System.Threading.ThreadHelper.ThreadStart()
InnerException:
下面给出MSDN给出的解决方案:
如何跨线程调用Windows窗体控件(http://msdn.microsoft.com/en-us/library/ms171728(VS.90).aspx)
摘取C#相关代码如下:
// This event handler creates a background thread that // attempts to set a Windows Forms control property // directly.private void setTextUnsafeBtn_Click (object sender, EventArgs e){ // Create a background thread and start it. this.demoThread = new Thread(new ThreadStart(this.ThreadProcUnsafe)); this.demoThread.Start(); // Continue in the main thread. Set a textbox value that // would be overwritten by demoThread if it succeeded. // This value will appear immediately, then two seconds // later the background thread will try to make its // change to the textbox. textBox1.Text = "Written by the main thread.";}// This method is executed on the worker thread. It attempts// to access the TextBox control directly, which is not safe.private void ThreadProcUnsafe(){ // Wait two seconds to simulate some background work // being done. Thread.Sleep(2000); this.textBox1.Text = "Written unsafely by the background thread.";}
上述代码并不能解决这个问题,在网上搜了一下,找到了这个方法,很好用:
先给出链接:http://www.shabdar.org/c-sharp/102-cross-thread-operation-not-valid.html
摘抄部分原文:
Solution
You can apply same solution to any windows control. All you have to do is, copySetControlValueCallback delegateand SetControlPropertyValue function from above code. For example if you want to set property of a label, useSetControlPropertyValue function.
SetControlPropertyValue(Label1, "Text", i.ToString());
Make sure you supply property value in correct type. In above example Text is a string property. This is why I am converting variablei tostring.
自己根据上面的代码对程序进行了修改,修改后的代码如下:
delegate void SetControlValueCallback(Control oControl, string propName, object propValue); private void SetControlPropertyValue(Control oControl, string propName, object propValue) { if (oControl.InvokeRequired) { SetControlValueCallback d = new SetControlValueCallback(SetControlPropertyValue); oControl.Invoke(d, new object[] { oControl, propName, propValue }); } else { Type t = oControl.GetType(); PropertyInfo[] props = t.GetProperties(); foreach (PropertyInfo p in props) { if (p.Name.ToUpper() == propName.ToUpper()) { p.SetValue(oControl, propValue, null); } } } } //这是根据需要改写的,用于给ListView指定列赋值的
delegate void SetListViewControlValueCallback(ListView oControl, int nItem, int nSubItem, string propValue); private void SetListViewControlPropertyValue(ListView oControl, int nItem, int nSubItem, string propValue) { if (oControl.InvokeRequired) { SetListViewControlValueCallback d = new SetListViewControlValueCallback(SetListViewControlPropertyValue); oControl.Invoke(d, new object[] { oControl,nItem,nSubItem, propValue }); } else { oControl.Items[nItem].SubItems[nSubItem].Text = propValue; } } private void WorkScanFileThread() { for (nDriveIndex = 0; nDriveIndex < DriveList.Count; nDriveIndex++) { SetControlPropertyValue(this.progressBar1, "value", 0); SetListViewControlPropertyValue(this.listView3, nDriveIndex,2, "Scaning..."); //执行的功能操作
SetListViewControlPropertyValue(this.listView3, nDriveIndex, 2, "Finished"); } }
这样问题就得到的完美的解决。
产生这个问题的主要原因是由于,控件不是线程安全性的,在线程中访问非线程安全性的操作会被抛出异常,提醒编程开发人员进行代码修改。
再给出两个相关的链接
http://blog.sina.com.cn/s/blog_4cb80898010009de.html
http://www.cnblogs.com/ini_always/archive/2011/04/26/2029409.html
- C# 多线程中更新窗体控件
- C#2005 多线程中调用窗体控件
- c# vs2005 多线程中调用窗体控件
- c# vs2005 多线程中调用窗体控件 (摘)
- C#中多线程更新Chart控件与BeginInvoke
- C#多线程窗体控件安全访问
- C#多线程窗体控件安全访问
- C#多线程窗体控件安全访问
- Android 多线程及多线程中更新控件。
- Android 多线程及多线程中更新控件。 .
- Android 多线程及多线程中更新控件。
- Android 多线程及多线程中更新控件。
- C#控件多线程更新用委托
- C# winform 多线程中创建等待窗体
- c#中跨窗体调用控件
- C#多线程窗体控件安全访问实现方法
- 多线程操作窗体控件
- C# Winform项目中多线程环境下, 如何跨线程对Window窗体控件进行安全访问?
- JavaScript 技巧
- ubuntu 安装 Insight
- android - GestureDetector 实现界面左右滑动效果的优化
- 表达式和运算符
- struts2 验证体式格式actingMassage actionError 和fieldError
- C# 多线程中更新窗体控件
- dba和sysdba的区别
- 网络攻击1
- 函数申明中的 __P 的作用
- T9输入法的实现
- windows 下 apache 动态缓存 ssi 配置
- 在XD 4.0 设置Policy
- linux学习笔记--总结
- http://blog.chinaunix.net/uid-22666718-id-1771703.html