【问题标题】:When the property is getted in a ForEach loop?何时在 ForEach 循环中获取属性?
【发布时间】:2009-12-30 13:49:13
【问题描述】:

我有一个像这样带锁的属性获取器:

Public ReadOnly Property ActiveClientList() as List(Of TcpClient)
    Get
        SyncLock(m_activeClientListLock)
            Return m_activeClientList
        End SyncLock
    End Get
End Property

当我执行 ForEach 循环时,何时获取属性?我的意思是,在这个循环中,当列表被锁定时?第一次检查?每次迭代?在整个循环中?

For Each client as TcpClient in Me.ActiveClientList

Next

提前致谢!

【问题讨论】:

    标签: .net multithreading locking foreach


    【解决方案1】:

    For Each 实际上是语法糖。编译器将其扩展为:

    Dim enumerator As IEnumerator(Of TcpClient)
    
    enumerator = Me.ActiveClientList.GetEnumerator()
    
    While enumerator.GetNext()
    
        Dim client As TcpClient
        client = enumerator.Current
    
        'Loop body inserted here.'
    
    End While
    

    抱歉,如果这不是真正的 VB.NET(我是 C# 男孩)。

    如您所见,对ActiveClientList 的调用发生了一次,就在循环开始时。

    【讨论】:

    • 非常好的解释。谢谢。
    • 你忘记了 Finally 块来处理枚举数。
    • 让我们不要为可怜的小伙子把事情搞得太复杂!如果他们真的想离开并确切地了解循环是如何扩展的,那么有比我的灰质更好的资源。
    【解决方案2】:

    在您的上述场景中,第一次初始化 for 循环时会获得一次锁。返回列表并释放锁,然后开始迭代。

    【讨论】:

      【解决方案3】:

      Me.ActiveClientList 将为您提供对 m_activeClientList 的引用,因此该引用将被获取一次(在循环启动和使用锁时)并在整个循环中使用。因此,这意味着如果列表的元素在循环期间发生更改(通过其他线程),您将不受保护。

      但是,如果您要实现的是对列表的同步访问(例如,如果它是共享列表或其他东西),请查看此链接: How to synchronize the access to a List<T> used in ASP.NET?

      您可以锁定SyncRoot 以锁定对列表的访问。

      【讨论】:

        【解决方案4】:

        您的锁定代码只会锁定 return 语句,不会锁定其他任何内容。
        不可能有多个语句锁定的情况。

        For Each 循环将读取一次属性,然后调用GetEnumerator

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2020-01-16
          • 2015-06-29
          • 2011-07-16
          • 2018-10-13
          • 2020-06-05
          • 1970-01-01
          • 1970-01-01
          • 2021-05-21
          相关资源
          最近更新 更多