后台线程集合中对象的线程安全刷新属性

时间:2012-10-02 06:47:59

标签: .net vb.net thread-safety

我有一个对象Product,它存储在我的应用程序的本地缓存中。使用一些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)吗?

处理此问题的最佳方法是什么?

1 个答案:

答案 0 :(得分:1)

当您使用对象的共享写访问时,您需要使用锁或信号量来避免冲突。执行此操作时,它将告诉其他线程等待对象解锁。这不需要cpu资源。当对象被解锁时,下一个线程可以先到先得的方式访问它(理论上)。

F.ex:

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