0

私は少しデータアクセスの最適化を行おうとしていましたが、知らないうちにマルチスレッドの状況に陥らない限り、辞書が同期していないように見える状況に遭遇しました。

GridLabelsの1つの列は、データアクセスを行うプロパティにバインドします。これは少し高価です。ただし、複数の行が同じ呼び出しを行うことになります。そのため、少しキャッシュを行うことで、パスで問題を回避できるはずです。

ただし、アプリの他の場所では、この同じコードがキャッシュが適切でない方法で呼び出されるため、オンデマンドでキャッシュを有効にする方法が必要でした。したがって、私のデータバインディングコードは次のようになります。

    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 に答える