【问题标题】:Backgroundworker is very slow, how to optimize?backgroundworker 很慢,如何优化?
【发布时间】:2012-01-03 15:43:19
【问题描述】:

我的结构如下:
OLD:
frmMain (WinForm)
uscStat(带网格的用户控件)

在 frmMain 中,我可以进行一些设置并通过 LinQ 将设置结果加载到 uscStat 的网格中。
f.e.:
frmMain

Private Sub rdbValue2_ValueChanged(sender As System.Object, e As System.EventArgs) Handles rdbValue2.ValueChanged  
  uscStat.Load(Value1,Value2,Value3,Value4, ...)  
End Sub  

uscStat

Public Sub Load(ByVal Value1, ByVal Value2, ByVal Value3, ...)

  ...
  Dim dt As New Datatable
  dt.Columns.Add(New DataColumn("Value1", GetType(Double)
  ...
  Dim res As IEnumerable = ReturnDatable(Value2, Value3, ...)
  Dim rowObj(6) As Object
  ...    
  For each item in res
    rowObj(1) = FuncXY(item.Value1)
    rowObj(2) = item.Value2
    ...
    dt.Rows.Add(rowObj)
  Next

  dg.Datasource = dt
End Sub

大约需要 30 秒,具体取决于用户设置。

新功能
添加:modCommon(模块)
为了传递所有变量,我在模块中添加了以下类:

Public Class clsStatValues
  Public Property Value1() As Boolean
  Get
    Return m_Value1
  End Get
  Set(value As Boolean)
    m_Value1 = value
  End Set
  End Property
  Private m_Value1 As Boolean
  Public Property Value2() As Integer
  Get
    Return m_Value2
  End Get
  Set(value As Integer)
    m_Value2 = value
  End Set
  End Property
  Private m_Value2 As Integer
  ...
End Class

我在 modCommon 中添加了以下 BackgroundWorker:

Public thStat As Backgroundworker

我在frmMain中初始化thStat:

thStat = New BackgroundWorker
AddHandler thStat.DoWork, AddressOf thStat_DoWork
AddHandler thStat.RunWorkerCompleted, AddressOf thStat_Completed
AddHandler thStat.ProgressChanged, AddressOf thStat_ProgressChanged
thStat.WorkerReportsProgress = True
thStat.WorkerSupportsCancellation = True

并创建了以下潜艇:

Private Sub thStat_DoWork(ByVal sender As Object, ByVal e As DoWorkEventArgs)
    Dim varStat As clsStatValues = e.Argument
    uscStat.Load(varStat.Value1, varStat.Value2, ...)
End Sub

并更改了设置-subs,例如:

Private Sub rdbValue2_ValueChanged(sender As System.Object, e As System.EventArgs) Handles rdbValue2.ValueChanged  
  Dim varStat As New clsStatValues
  varStat.Value1 = True
  varStat.Value2 ...
  ...
  thStat.RunWorkerAsync(varStat) 
End Sub  

uscStat 我更改/添加了以下内容:

Public Sub Load(ByVal Value1, ...)
  ...
  Me.Invoke(New AddDataSourceToGrid(AddressOf AddDataSourceToGridFunction), GetDatatable(Value1, Value2, ...))
  ...
End Sub

Delegate Sub AddDataSourceToGrid(ByRef tmpDt As DataTable)

Private Sub AddDataSourceToGridFunction(ByRef tmpDt As DataTable)
    dg.DataSource = tmpDt
End Sub

Public Function GetDatatable(ByVal Value1, ByVal Value2, ByVal Value3, ...) As Datatable

  ...
  Dim dt As New Datatable
  dt.Columns.Add(New DataColumn("Value1", GetType(Double)
  ...
  Dim res As IEnumerable = ReturnDatable(Value2, Value3, ...)
  Dim resultCount = res.AsQueryable.Count
  Dim ReportEvery As Double = resultCount/100
  Dim staticReportEvery As Double = ReportEvery
  Dim count As Integer = 0
  Dim Percent As Integer = 0

  Dim rowObj(6) As Object
  ...    
  For each item in res
    count += 1
    If count > ReportEvery then
      Percent += 1
      thStat.ReportProgress(Percent, count & " of " & resultCount)
      ReportEvery += staticReportEvery
    End If
    rowObj(1) = FuncXY(item.Value1)
    rowObj(2) = item.Value2
    ...
    dt.Rows.Add(rowObj)
  Next

  Return dt
End Sub

使用相同的用户设置大约需要 5 分钟,太慢了。
我该如何改进它?

【问题讨论】:

  • ReportProgress 很昂贵,不要为每一行调用它。如果没有帮助,请使用分析器。
  • 嗯,ReportProgress 被调用了 100 次(1%、2%,...),而不是每一行。这还是太多了吗?

标签: vb.net linq delegates backgroundworker invoke


【解决方案1】:

如果我理解正确,您可以将一个 DataTable 复制到另一个 DataTable 并将 FuncXY 应用于列。我不知道 FuncXY 是做什么的。是否可以使用 SQL 查询来做到这一点?这比遍历单个记录要快得多。

【讨论】:

  • 我不认为我复制了数据表,因为我将变量作为参考传递。纠正我我错了。把 FuncXY 直接放在 SQL 里?我先说:不。但我会考虑的。但实际上它在没有 Backgroundworker 的情况下运行相对较快。
猜你喜欢
  • 1970-01-01
  • 2014-02-05
  • 2021-10-12
  • 1970-01-01
  • 2014-01-09
  • 1970-01-01
  • 1970-01-01
  • 2012-03-05
  • 1970-01-01
相关资源
最近更新 更多