VB.net跨线程操作无效
我正在尽力弄清楚如何解决我收到的此错误:
跨线程操作无效:从创建它的线程以外的线程访问控制“ListView1”。
我有一个后台工作人员,它从 Excel 工作表中提取单元格并将它们放入列表视图中。
表单加载后,我这样做:
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
Call createListView()
End Sub
Private Sub createListView()
ListView1.View = View.Details
ListView1.GridLines = True
ListView1.FullRowSelect = True
ListView1.HideSelection = False
ListView1.MultiSelect = False
ListView1.Columns.Add("Column Name", 150)
ListView1.Columns.Add("Column Number", 150)
End Sub
然后在用户选择文件后调用后台工作程序:
If openFileDialog1.ShowDialog() = DialogResult.OK Then
stFilePathAndName = openFileDialog1.FileName
ProgressBar1.Style = ProgressBarStyle.Marquee
BGWxml2excel = New System.ComponentModel.BackgroundWorker
BGWxml2excel.WorkerReportsProgress = True
BGWxml2excel.WorkerSupportsCancellation = True
BGWxml2excel.RunWorkerAsync()
End If
然后我处理获取Excel列数和值,以便我可以用它填充列表视图:
Private Sub BGWxml2excel_DoWork(ByVal sender As Object, ByVal e As System.ComponentModel.DoWorkEventArgs) Handles BGWxml2excel.DoWork
Call xml2Excel(stFilePathAndName)
End Sub
Private Sub xml2Excel(ByRef theDirOfFile As String)
Dim xlsApp As Excel.Application
Dim xlsWB As Excel.Workbook
Dim xlsSheet As Excel.Worksheet
Dim columnCount As Integer = 0
xlsApp = New Excel.Application
xlsApp.Visible = False
xlsApp.DisplayAlerts = False
xlsWB = xlsApp.Workbooks.OpenXML(Filename:=theDirOfFile, LoadOption:=XlXmlLoadOption.xlXmlLoadImportToList)
xlsSheet = xlsWB.Worksheets(1)
xlsSheet.Select()
columnCount = xlsSheet.UsedRange.Columns.Count
Dim lvi As New ListViewItem
Dim x As Integer = 1
Do Until x = columnCount + 1
lvi.Text = xlsSheet.Cells(1, x).value
lvi.SubItems.Add(x)
ListView1.Items.Add(lvi)
x = x + 1
Loop
'xlsSheet.SaveAs("c:\_tempExcelFile.xlsx", FileFormat:=51, CreateBackup:=False)
xlsWB.Close()
xlsApp.Quit()
End Sub
错误在这一行:
ListView1.Items.Add(lvi)
我可以做什么为了纠正这个奇怪的问题该怎么办?
谢谢!
大卫
I am trying my best to figure out how to go about this error i am reciving:
Cross-thread operation not valid: Control 'ListView1' accessed from a thread other than the thread it was created on.
I have a backgroundworker thats extracting cells from an excel worksheet and placing them into the listview.
Upon form load i do this:
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
Call createListView()
End Sub
Private Sub createListView()
ListView1.View = View.Details
ListView1.GridLines = True
ListView1.FullRowSelect = True
ListView1.HideSelection = False
ListView1.MultiSelect = False
ListView1.Columns.Add("Column Name", 150)
ListView1.Columns.Add("Column Number", 150)
End Sub
Then i call the backgroundworker after the user selects a file:
If openFileDialog1.ShowDialog() = DialogResult.OK Then
stFilePathAndName = openFileDialog1.FileName
ProgressBar1.Style = ProgressBarStyle.Marquee
BGWxml2excel = New System.ComponentModel.BackgroundWorker
BGWxml2excel.WorkerReportsProgress = True
BGWxml2excel.WorkerSupportsCancellation = True
BGWxml2excel.RunWorkerAsync()
End If
Then i process with getting the excel column count and values so that i can populate the listview with it:
Private Sub BGWxml2excel_DoWork(ByVal sender As Object, ByVal e As System.ComponentModel.DoWorkEventArgs) Handles BGWxml2excel.DoWork
Call xml2Excel(stFilePathAndName)
End Sub
Private Sub xml2Excel(ByRef theDirOfFile As String)
Dim xlsApp As Excel.Application
Dim xlsWB As Excel.Workbook
Dim xlsSheet As Excel.Worksheet
Dim columnCount As Integer = 0
xlsApp = New Excel.Application
xlsApp.Visible = False
xlsApp.DisplayAlerts = False
xlsWB = xlsApp.Workbooks.OpenXML(Filename:=theDirOfFile, LoadOption:=XlXmlLoadOption.xlXmlLoadImportToList)
xlsSheet = xlsWB.Worksheets(1)
xlsSheet.Select()
columnCount = xlsSheet.UsedRange.Columns.Count
Dim lvi As New ListViewItem
Dim x As Integer = 1
Do Until x = columnCount + 1
lvi.Text = xlsSheet.Cells(1, x).value
lvi.SubItems.Add(x)
ListView1.Items.Add(lvi)
x = x + 1
Loop
'xlsSheet.SaveAs("c:\_tempExcelFile.xlsx", FileFormat:=51, CreateBackup:=False)
xlsWB.Close()
xlsApp.Quit()
End Sub
The error is on this line:
ListView1.Items.Add(lvi)
What can i do in order to correct this odd proglem?
Thanks!
David
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
问题是只有UI线程可以更新UI。由于您正在从工作线程向
ListView
添加项目,因此您会收到此异常。要解决此问题,您可以将要添加到列表视图的项目存储在共享变量中(UI 线程和您的工作线程都可以访问该变量),在表单上放置一个计时器(以便 UI 线程触发 tick 事件) handler) 并在刻度处理程序中添加项目。
淡化示例(在 C# 中,因为它对我来说要快得多:-)):
The problem is that only the UI thread can update the UI. Because you are adding an item to the
ListView
from your worker, you are getting this exception.To fix this, you could store items that you want to add to the listview in a shared variable (one to which both the UI thread and your worker have access), put a timer on your form (so the UI threads hits the tick event handler) and add the items within the tick handler.
Watered-down example (in C#, because it's a lot faster for me :-) ):
只有UI线程可以访问UI。您的后台工作人员在另一个线程上。您需要使用 .InvokeRequired/.Invoke 返回 UI 线程。
http://msdn.microsoft.com/en- us/library/ms171728(v=vs.80).aspx
后台工作者的事件处理程序将在主线程上引发;您可以在那里安全地更改用户界面。但实际上在后台线程中,您必须调用。像这样:
Only the UI thread can access the UI. Your background worker is on another thread. You'll need to use .InvokeRequired/.Invoke to get back to the UI thread.
http://msdn.microsoft.com/en-us/library/ms171728(v=vs.80).aspx
The event handler's for the background worker will be raised on the main thread; you can safely alter the UI there. But actually in the background thread, you'll have to invoke. Like this: