VB.net跨线程操作无效

发布于 2024-10-19 05:39:39 字数 2313 浏览 1 评论 0原文

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

跨线程操作无效:从创建它的线程以外的线程访问控制“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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

情释 2024-10-26 05:39:39

问题是只有UI线程可以更新UI。由于您正在从工作线程向 ListView 添加项目,因此您会收到此异常。

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

淡化示例(在 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);
        }
    }
}

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 :-) ):

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);
        }
    }
}
久光 2024-10-26 05:39:39

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

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

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

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

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:

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
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文