【问题标题】:Reading ListView from BackgroundWorker从 BackgroundWorker 读取 ListView
【发布时间】:2016-07-12 02:31:42
【问题描述】:

我已尝试进行一些搜索,但在我的一生中,我似乎无法找到答案或可行的建议解决方案。这可能是我的理解,但希望问我自己的问题会给我一个有效的答案: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一行

感谢您的帮助!

【问题讨论】:

  • 你为什么使用BackgroundWorker?您是否在加载项目时尝试阅读它们?
  • 我正在尝试使它在读取数据时不会锁定 UI,因为它会在后台将其放入数据库中。我希望 UI 显示一个加载图标,以便最终用户知道发生了什么事。
  • 那么您想在后台线程上进行 IO 操作并在处理文件内容时逐步更新 ListView?我问,因为,在您的示例代码中,您试图在前台线程上运行代码以构建一个字符串 - 目前尚不清楚您为什么要这样做。
  • 我有在后台线程上填充 ListView 的代码(我没有这样做,仅供参考),但这个问题只是读取 ListView 中的数据。我正在构建一个语句,该语句将在该过程的后期生成一个 SQL 语句,但主要问题不是字符串的构建,而是 For Each ListItem...
  • 您使用的是ReportProgress 方法吗?然后处理 ProgressChanged 事件以更新 UI。您可能会发布更多代码以获得更多帮助....

标签: vb.net multithreading listview backgroundworker


【解决方案1】:

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

  • 所有内容都包含在 String 中,这意味着您将有代码将其转换为其他类型
  • 它不支持数据绑定,这意味着您必须手动创建行...
  • ...然后再对其进行迭代以获取数据。

DataGridViewDataTable 会更简单:当用户将数据输入到控件中时,它会以正确的类型存储在表中。将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]
[酸女祭司]、[hendrerit nibh tempor]、[鲈鱼]
【冰封正义】、【Interdum ex felis】、【剑鱼】

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

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

【讨论】:

  • 谢谢,我将开始查看您在原始帖子中提到的数据集,因为从长远来看,我可以看到它的优势,特别是最终将加载更多数据并且ListView 只能容纳这么多行。感谢您的帮助,幸运的是我没有浪费一天的时间,因为我采用了与您发布的解决方案类似的方法来解决问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-11-08
  • 1970-01-01
  • 2012-01-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多