I have an Object, a Product, which is stored in a local cache in my app. This product cache is loaded from the database using some ORM code, which I can’t easily change. For simplicity, the Product is:
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
Products are stored in a local cache:
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
This is heavily simplified, but you get the idea.
The Rank property is an unbound, calculated field based on all sales in the past 90 days, so that common products appear higher in a search. I want to generate the rank on a background thread – as it can be time consuming, and refresh it from time to time. Something like this:
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
The cache may be used while the rank is being updated, resulting in dirty reads, but I am happy to live with that. What I do want to do is to perform this in a thread safe manner. That is, update the collection without worrying about if things are added and removed, etc.
Can I use a System.ComponentModel.BackgroundWorker to perform this update? I use lots of threading in the main UI for things like this, but this is a non-UI class in a DLL. I was thinking of pulling the cache into a Dictionary(of Integer, Product) first?
What is the best way to handle this?
As you using shared write access to objects you will need to use locks or semaphores to avoid collisions. When doing this it will tell other threads to wait until the object is unlocked. This takes no cpu-resources. When the object is unlocked the next thread can access it on a first-come-first-served basis (in theory).
F.ex:
VB.Net:
C#:
Example comes from a free e-book which is an excellent reference on multi-threading:
http://www.albahari.com/threading/part2.aspx#_Locking