【问题标题】:How to deal with lists of time-consuming objects如何处理耗时对象列表
【发布时间】:2016-12-31 23:12:31
【问题描述】:

在 .Net 4.5 中,我有一些列表,其中包含加载耗时的对象。加载一个包含 5000 个对象的列表大约需要 5 秒,因此每个循环都需要相当长的时间来执行。

由于对象的初始化需要花费所有时间,我一直想知道是否有一种列表类型,或者有一种方法可以制作这样的列表,在需要时逐步加载对象。

类似于列表的东西,它知道有多少对象,但仅在检索对象时实例化对象。这存在吗?或者有没有可能做一个这样的清单?

我正在寻找有关如何完成此操作的建议(如果可行的话),因此 bot C# 或 VB.Net 代码会很好。因此我添加了两个标签。

编辑

我应该补充一点,我尝试过使用延迟加载,但这似乎只是延迟了列表的加载,这并不是真正的解决方案。

编辑

这是我现在使用的。请注意,我删除了使用延迟加载的蹩脚尝试并恢复到我昨天使用的方式(这实际上是没有Lazy 对象的延迟加载)

Public Class SISOverlayItemList : Inherits SISBaseObject : Implements IEnumerable(Of SISOverlayItem)

Default Public ReadOnly Property Item(ByVal Index As Integer) As SISOverlayItem
    Get
        Return New SISOverlayItem(Me.List(Index).ID, Me.Parent)
    End Get
End Property

Public ReadOnly Property Items As List(Of SISOverlayItem)
    Get
        Dim output As New List(Of SISOverlayItem)

        Call Me.List.Items.AsParallel.ForAll(Sub(i) output.Add(New SISOverlayItem(i.ID, Me.Parent))

        Return output
    End Get
End Property

Public ReadOnly Property Parent As SISOverlay
    Get
        Return Me._Parent
    End Get
End Property

Private ReadOnly Property List As SISList
    Get
        If Me._List Is Nothing Then
            Me._List = Me.Application.Lists(Me.Name)
        End If
        Call Me.Refresh()
        Return Me._List
    End Get
End Property

Private _List As SISList
Private _Parent As SISOverlay

Public Sub New(ByVal Parent As SISOverlay)

    Me._Parent = Parent
    Me._Application = Parent.Application
    Me._Name = String.Format("Overlay_{0}_Items", Parent.Name)
    Call Me.Refresh()

End Sub

Public Sub Refresh()

    Call Me.Application.Lists(Me.Name).ScanOverlay(Me.Parent)

End Sub

Public Function GetEnumerator() As IEnumerator(Of SISOverlayItem) Implements IEnumerable(Of SISOverlayItem).GetEnumerator

    Return Me.Items.GetEnumerator()

End Function

Private Function GetEnumerator1() As IEnumerator Implements IEnumerable.GetEnumerator

    Return Me.GetEnumerator

End Function

结束类

Items 属性将所有对象从 List 转换为当前列表 (SISOverlayItem) 的项目需要很长时间。如果实例化SISOverlayItem 所需的ID 参数需要对存储在List 的每个项目中的Application 对象进行API 调用,那么在转换过程中会花费什么时间。

如果可以小批量执行这些调用,那么它应该消除实例化列表中每个对象所需的长时间延迟。

【问题讨论】:

  • c# 还是 vb.net?你不能两者兼得……你所描述的确实通常是作为女士加载来实现的。如果它对您不起作用,那么您可能做错了。如果没有您提供的更多详细信息,无法更具体...
  • 5 秒初始化如何给您带来问题?您是否尝试更新/填充 UI?只是想知道从什么角度看
  • 我正在寻找 C# 或 VB.Net 中的解决方案。我会适应我得到的任何东西。我试图延迟加载整个列表,Lazy(Of List(Of MyObject))。那真的没有任何改变。我还尝试了List(Of Lazy(Of MyObject)),它非常快速地加载了正确数量的项目,但所有项目都有价值Nothing,所以我无法枚举。我以前从未这样做过,所以我不确定我在第二个变体中做错了什么。
  • 能否贴一些代码,让我们分析一下,看看问题出在哪里。
  • @RobGoodwin 5 秒适用于包含大约 5000 个对象的测试列表,但列表中可能有数千个对象,这将是相当长的延迟。如果没有其他方法,我会接受打击,但如果可以让它更快,那会让我感觉很好,内心很模糊。

标签: c# .net vb.net list


【解决方案1】:

听起来这些对象还没有全部存在,这是需要这么长时间的部分原因。如果您不需要将项目集合作为列表,那么值得研究yield return。这给出了一个可以查询、过滤或枚举的IEnumerable

它可能看起来像这样:

public readonly IEnumerable<SISOverlayItem> Items
{
    get
    {
        SISOverlayItem myItem = intermediateList.DoSomeWork();
        yield return myItem;
    }
}

这可能不切实际。此外,如果涉及大量处理,这可能更适合作为方法而不是属性。如果您知道如何过滤集合,您可以执行以下操作:

public IEnumerable<SISOverlayItem> ProduceSelectedItems()
{
    var intermediateItems = from item in intermediateList
                            where item.isSelected
                            select item;
    foreach (var item in intermediateItems)
    {
        yield return item.DoSomeWork();
    }
}

抱歉,我手头没有可检查的 Visual Studio,但我认为类似的东西可能会有所帮助。概述这种方法的另一个问题是here

【讨论】:

  • 谢谢,看起来很有希望。不过,我必须先将我的项目翻译成 C#,因为在 VB.Net 中实现yield 看起来真的很头疼。当我有机会进行翻译时,我会告诉你我在哪里。
  • 快速更新。我完成了翻译。不幸的是,我刚刚发现我不能只使用我写的代码。该项目中还有其他一些类,它们是用 VB.Net 编写的(直接 VB6 端口,不是我编写的),它们一团糟,我需要一周时间才能整理出来,因为我什至不知道它们是什么做。所以我必须先集中精力完成其他工作,抱歉。
  • 听起来很难构建代码!我很高兴你找到了一些有用的东西。
猜你喜欢
  • 2016-07-01
  • 2020-07-13
  • 1970-01-01
  • 2018-02-08
  • 1970-01-01
  • 2021-09-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多