2009-12-30 25 views
2

我有這樣一個帶有鎖屬性的getter:當屬性在ForEach循環中得到時?

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

當我做一個foreach循環時的財產getted?我的意思是,在這個循環中,列表被鎖定?在第一次檢查?在每次迭代?在整個循環?

For Each client as TcpClient in Me.ActiveClientList 

Next 

在此先感謝!

回答

2

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的呼叫發生一次,就在循環的開始。

+0

真的很好的解釋。謝謝。 – 2009-12-30 14:03:18

+1

你忘了'Finally'塊處置枚舉。 – SLaks 2009-12-30 14:07:32

+1

讓我們不要爲這個可憐的小夥子過分複雜的事情!如果他們真的想離開並學習循環如何擴展,那麼比我的灰色物質有更好的資源。 – 2009-12-30 14:26:29

2

在你上面的場景中,for循環首先初始化時獲得一次鎖。該列表返回並釋放該鎖,然後開始迭代。

2

Me.ActiveClientList會給你的m_activeClientList的引用,所以這個參考值將取一個時間(循環開始,並使用鎖)和整個循環使用。所以這意味着如果在你的循環中列表中的元素改變了(通過其他線程),你就不會受到保護。

但是,如果你要實現的目標是到列表的同步訪問(例如,如果它是一個共享的列表或東西),然後檢查這個環節出: How to synchronize the access to a List<T> used in ASP.NET?

您可以鎖定SyncRoot鎖定訪問到名單。

2

你的鎖碼只會鎖定return語句,而沒有別的。
沒有可能的方案中,你會鎖定一個以上的語句。

For Each循環會讀取一次屬性,然後調用GetEnumerator