从 BackgroundWorker 读取 ListView

Reading ListView from BackgroundWorker

我已经尝试进行一些搜索,但对于我来说,我似乎无法找到答案或建议的有效解决方案。这可能是我的理解,但希望问我自己的问题会给我一个有效的答案:o)

我有一个 Windows 表单应用程序,它包含一个项目,ListView1

此 ListView 已通过在主 UI 线程上完成的拖放从文件中添加项目,没有后台工作程序,它由大约 1500 行组成。

我现在正在尝试让后台工作人员读取此 ListView,但我遇到了跨线程错误,因为 ListView1 不是在同一线程上创建的。

错误出现在最简单的代码段上,但我似乎无法想出解决方法或实现调用等。

    For i = 0 To Me.ListView1.Items.Count - 1

        ValueStatement = ValueStatement & "(" & Me.ListView1.Items(i).SubItems(0).Text

        If i = Me.ListView1.Items.Count - 1 Or counter = 500 Then
            CommaTerminate = ";"
        Else
            CommaTerminate = ","
        End If


        For y = 0 To Me.ListView1.Columns.Count - 1
            ValueStatement = ValueStatement & "'" & Me.ListView1.Items(i).SubItems(y).Text & "'"
            If y = Me.ListView1.Columns.Count - 1 Then
                ValueStatement = ValueStatement & ")"
            Else
                ValueStatement = ValueStatement & ","
            End If

        Next
        ValueStatement = ValueStatement & CommaTerminate & vbNewLine


        If counter = 500 Then
            SQLStatement = "INSERT INTO RAW_CLI_DATA_" & GlobalVariables.CDR_Company & " VALUES " & vbNewLine & ValueStatement
            GenericDatabaseRequest(SQLStatement, "Loading RAW table with data..")
            counter = 0
            ValueStatement = ""
        End If

        counter = counter + 1
    Next

错误出现在行ValueStatement = ValueStatement & "(" & Me.ListView1.Items(i).SubItems(0).Text

感谢您的帮助!

听起来你很早就走错了路。 ListView 非常不适合数据库操作:

  • 所有内容都包含在 String 中,这意味着您可以在某处使用代码将其转换为其他类型
  • 它不支持数据绑定,这意味着您必须手动创建行...
  • ...然后迭代它们以将数据捞回。

A DataGridViewDataTable 会更简单:当用户将数据输入控件时,它将存储在 table 中并作为正确的类型。将 DataTable 设置为 DatasourceDataGridView 将为您创建显示(行和列)。

SQLite 执行 INSERT 会消耗一些时间,但看起来您也在花费大量时间迭代和连接 SQL。无论如何,处理数据通常比用户查看数据要好,因此提取数据并将其传递给工作人员。

首先,将 ListView 中的数据吸取到 String()() 容器中:

Dim data = lv.Items.
    Cast(Of ListViewItem).
    Select(Function(s) New String() {s.SubItems(0).Text,
                                     s.SubItems(1).Text,
                                     s.SubItems(2).Text}).
        ToArray()

然后传给BackGroundWorker:

bgw.RunWorkerAsync(data)

DoWork事件:

Private Sub bgw_DoWork(sender As Object, e As DoWorkEventArgs) Handles bgw.DoWork

    ' unbox the data
    Dim dataToInsert = CType(e.Argument, String()())

    For n As Int32 = 0 To 2
        Console.WriteLine("[{0}], [{1}], [{2}]", dataToInsert(n)(0),
                          dataToInsert(n)(1),
                          dataToInsert(n)(2))
    Next

End Sub

结果:

[Patient Tempest], [Lorem ipsum dolor sit], [Swordfish]
[Sour Priestess], [hendrerit nibh tempor], [Perch]
[Frozen Justice], [Interdum ex felis], [Swordfish]

它正确地打印了我放入 LV 的随机数据。

这将允许您处理 BackGroundWorker 中的 ListView 数据,但它不会真正节省任何时间,它只是保持 UI 解锁。真正的问题在别处,可能在数据库操作中。