0

Productアプリのローカル キャッシュに保存されているオブジェクト aがあります。この製品キャッシュは、簡単に変更できない ORM コードを使用してデータベースから読み込まれます。簡単にするために、次のProductとおりです。

Public Class Product
    Public Property ID as Integer
    Public Property Name as String
    Public Property Price as Decimal
    Public Property Rank as Integer
End Class

製品はローカル キャッシュに保存されます。

   Public Class ProductList
       Public Shared Function GetCache as List(Of Product)
           Static _List as List(Of Product)
           If _List is Nothing then
               'Code to load Data and populate List from DB
           End If
           Return _List
       End Function
    End Class

これは非常に単純化されていますが、アイデアは得られます。

このRankプロパティは、過去 90 日間のすべての売上に基づくバインドされていない計算フィールドであるため、一般的な製品が検索で上位に表示されます。時間がかかる可能性があるため、バックグラウンドスレッドでランクを生成し、時々更新したいと考えています。このようなもの:

Public Sub UpdateRank
    Dim dt as Datatable
    dt = GetDataTable("exec usp_GetProductRank") 'Returns [ID, Rank]
    For each row in dt.rows
        _prod = getCache.getbyID(row.item(0))
        If _prod isnot Nothing then
            _prod.rank = row.item(1)
        End If
    Next
End Sub

ランクの更新中にキャッシュが使用される可能性があり、その結果ダーティ リードが発生する可能性がありますが、私はそれを喜んで受け入れています。私がやりたいことは、これをスレッドセーフな方法で実行することです。つまり、追加や削除などを気にせずにコレクションを更新します。

を使用しSystem.ComponentModel.BackgroundWorkerてこの更新を実行できますか? このようなことのためにメイン UI で多くのスレッドを使用しますが、これは DLL の非 UI クラスです。キャッシュをDictionary(of Integer, Product)最初に引っ張ることを考えていましたか?

これを処理する最善の方法は何ですか?

4

1 に答える 1

1

オブジェクトへの共有書き込みアクセスを使用する場合、衝突を避けるためにロックまたはセマフォを使用する必要があります。これを行うと、オブジェクトがロック解除されるまで待機するように他のスレッドに指示します。これは、CPU リソースを必要としません。オブジェクトがロック解除されると、次のスレッドは先着順でアクセスできます (理論上)。

例:

VB.Net:

Class ThreadSafe

    Private Shared _locker As Object = New Object

    Private Shared Sub Go()
        SyncLock _locker
            If (_val2 <> 0) Then
                Console.WriteLine((_val1 / _val2))
            End If
            _val2 = 0
        End SyncLock
    End Sub
End Class

C#:

class ThreadSafe
{
  static readonly object _locker = new object();
  static int _val1, _val2;

  static void Go()
  {
    lock (_locker)
    {
      if (_val2 != 0) Console.WriteLine (_val1 / _val2);
      _val2 = 0;
    }
  }
}

例は、マルチスレッドに関する優れたリファレンスである無料の電子書籍からのものです: http://www.albahari.com/threading/part2.aspx#_Locking

于 2012-10-02T07:20:38.820 に答える