0

我试图做一些数据访问优化,但我遇到了一个字典似乎以一种不可能的方式不同步的情况,除非我在不知不觉中进入了多线程情况。

一列 GridLabels 绑定到一个进行数据访问的属性——这有点贵。但是,多行最终会发出相同的调用,所以我应该能够通过做一些缓存来解决任何问题。

但是,在应用程序的其他地方,同样的代码以不适合缓存的方式调用,我需要一种方法来按需启用缓存。所以我的数据绑定代码如下所示:

    OrderLabelAPI.MultiSyringeCacheEnabled = True
    Me.GridLabels.DataBind()
    OrderLabelAPI.MultiSyringeCacheEnabled = False

发生缓存的昂贵调用如下所示:

    Private Shared MultiSyringeCache As New Dictionary(Of Integer, Boolean)
    Private Shared m_MultiSyringeCacheEnabled As Boolean = False

    Public Shared Function IsMultiSyringe(orderLabelID As Integer) As Boolean
        If m_MultiSyringeCacheEnabled Then
            'Since this can get hit a lot, we cache the values into a dictionary. Obviously,
            'it goes away after each request. And the cache is disabled by default.
            If Not MultiSyringeCache.ContainsKey(orderLabelID) Then
                MultiSyringeCache.Add(orderLabelID, DoIsMultiSyringe(orderLabelID))
            End If

            Return MultiSyringeCache(orderLabelID)
        Else
            Return DoIsMultiSyringe(orderLabelID)
        End If
    End Function

这是 MultiSyringeCacheEnabled 属性:

    Public Shared Property MultiSyringeCacheEnabled As Boolean
        Get
            Return m_MultiSyringeCacheEnabled
        End Get
        Set(value As Boolean)
            ClearMultiSyringeCache()
            m_MultiSyringeCacheEnabled = value
        End Set
    End Property

非常非常罕见(不可重现的罕见......)我会得到以下异常:字典中不存在给定的键。

如果您仔细查看缓存代码,这是不可能的,因为它所做的第一件事就是确保密钥存在。如果 DoIsMultiSyringe 篡改了字典(明确地或通过设置 MultiSyringeCacheEnabled),这也可能导致问题,有一段时间我认为这一定是罪魁祸首。但事实并非如此。我已经非常仔细地检查过代码好几次了。我会把它贴在这里,但它会进入比合适的更深的对象图。

所以。我的问题是,datagridview 数据绑定实际上是否会陷入某种导致字典被占用的滑稽多线程情况?我是否缺少共享成员的某些方面?

我实际上已经从项目中删除了这段代码,但我想了解我缺少什么。谢谢!

4

1 回答 1

1

由于这是 ASP.NET,因此您有一个隐式的多线程方案。您正在使用共享变量(请参阅What is the use of a shared variable in VB.NET?),它(正如关键字所暗示的)跨多个线程(来自访问该站点的不同人员)“共享”。

您可以很容易地遇到一个访问者的线程到达这里的场景:

'Since this can get hit a lot, we cache the values into a dictionary. Obviously,
'it goes away after each request. And the cache is disabled by default.
If Not MultiSyringeCache.ContainsKey(orderLabelID) Then
    MultiSyringeCache.Add(orderLabelID, DoIsMultiSyringe(orderLabelID))
End If

' My thread is right here, when you visit the site

Return MultiSyringeCache(orderLabelID)

然后你的线程进来并取代我的线程:

Set(value As Boolean)
    ClearMultiSyringeCache()
    m_MultiSyringeCacheEnabled = value
End Set

然后我的线程将在您清除字典后尝试从字典中读取一个值。

也就是说,我不确定您期望从每次请求中清除的“缓存”中获得什么性能优势。看起来你不应该简单地让这个变量共享——让它成为一个实例变量——并且任何访问它的用户请求都会有他们自己的副本。

于 2012-06-14T15:04:21.220 回答