【问题标题】:VB.net Cross-thread operation not valid [duplicate]VB.net跨线程操作无效[重复]
【发布时间】:2011-02-25 14:19:27
【问题描述】:

我正在尽力弄清楚如何解决我收到的这个错误:

跨线程操作无效:控件“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

然后我在用户选择文件后调用backgroundworker:

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)

我能做些什么来纠正这个奇怪的问题?

谢谢!

大卫

【问题讨论】:

    标签: vb.net visual-studio-2010 listview backgroundworker


    【解决方案1】:

    问题是只有 UI 线程可以更新 UI。因为您正在从您的工作人员向ListView 添加一个项目,所以您会收到此异常。

    要解决此问题,您可以将要添加到列表视图的项目存储在一个共享变量中(UI 线程和您的工作人员都可以访问该变量),在您的表单上放置一个计时器(以便 UI 线程命中刻度事件处理程序)并在刻度处理程序中添加项目。

    淡化示例(在 C# 中,因为它对我来说要快得多 :-)):

    private List<ListViewItem> _itemsToBeAdded = new List<ListViewItem>();
    private readonly object _lockObject = new object();
    
    // worker method:
    private void xml2Excel(string input)
    {
        // do some processing...
        ListViewItem lvi = new ListViewItem();
        // set up lvi
    
        lock(_lockObject)
        {
            _itemsToBeAdded.Add(lvi);
        }
    }
    
    private void timer1_Tick(object sender, EventArgs e)
    {
        lock(_lockObject)
        {
            foreach(var item in _itemsToBeAdded)
            {
                ListView1.Add(item);
            }
        }
    }
    

    【讨论】:

      【解决方案2】:

      只有 UI 线程可以访问 UI。您的后台工作人员在另一个线程上。您需要使用 .InvokeRequired/.Invoke 来返回 UI 线程。

      http://msdn.microsoft.com/en-us/library/ms171728(v=vs.80).aspx

      后台工作者的事件处理程序将在主线程上引发;您可以在那里安全地更改 UI。但实际上在后台线程中,您必须调用。像这样:

      Delegate Sub SetTextCallback([text] As String)
      
      Private Sub SetText(ByVal [text] As String)
      
              ' InvokeRequired required compares the thread ID of the
              ' calling thread to the thread ID of the creating thread.
              ' If these threads are different, it returns true.
              If Me.textBox1.InvokeRequired Then
                  Dim d As New SetTextCallback(AddressOf SetText)
                  Me.Invoke(d, New Object() {[text]})
              Else
                  Me.textBox1.Text = [text]
              End If
          End Sub
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2012-08-22
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2010-12-04
        • 1970-01-01
        相关资源
        最近更新 更多