2011-09-01 159 views
0

所以我看到好玩東西在玩線程。c#線程同步問題

我有一個方法,啓動2個線程並繼續其生活,我試着做以下事情以保持安全。

bool CopyOk1 = false; 
    bool CopyOk2 = false; 
    new Thread(() => FirstMethod(tempList1, ref CopyOk1)).Start(); 
    new Thread(() => SecondMethod(tempList2, ref CopyOk2)).Start(); 
    var spinner = new SpinWait(); 
    while (!CopyOk1 || !CopyOk2) 
     spinner.SpinOnce(); 

然後在這兩種方法我開始用下面的

private static void FirstMethod(List<T> templist, ref bool CopyOk) 
    { 
     var temp = new T[templist.Count]; 
     templist.CopyTo(temp); 
     CopyOk = true; 
     //moves on 
    } 

我在這裏的目的是要複製傳遞的列表,以便我可以改變和安全地使用線程內儘快疏通調用程序線程。

我的問題是,在第二種方法不可預知的情況下,數組初始化和列表CopyTo基本列表之間的變化,不知何故,通過某些東西。

這些列表程序線程內創建,並沒有實際使用後的線程開始,所以我絕對NO知道如何/爲什麼發生這種情況。

毫無疑問,我在這裏做錯了什麼,但我的高超技巧不會讓我看到,任何幫助表示讚賞。

+5

你可以添加上面定義和分配tempList1&2的代碼嗎? – bryanmac

+0

我相信@ bryanmac完全釘了它。 templist的來源可以在templist定義後修改。 –

+0

您似乎很有可能在兩個tempLists之間共享某些值(引用)。向我們展示填充它們的代碼。 –

回答

1

在您發佈表明,你正在做什麼錯誤的代碼沒有。問題必須存在於其他地方 - 最有可能的是,正如評論者所建議的,在填充List1/List2的代碼中。如果你也是線程化的,也許你並沒有等待那個線程在繼續之前完成填充列表?

0

試試這個,檢查行爲

private static void FirstMethod(List<T> templist, ref bool CopyOk) 
{ 
    T[] temp; 

    lock (templist) 
    { 
     temp = new T[templist.Count]; 
     templist.CopyTo(temp); 
    } 
    CopyOk = true; 
    //moves on 
} 
+0

只有在線程啓動後修改templist時纔會修復此問題。 –

+0

@Thiago:你聲稱它不是,但你聲稱它是。如果你有一個你不明白的問題,不要忽視任何建議。 –

+0

如果你在任何地方鎖定列表,這將解決問題,但它本身並不會在功能上有意義。 –

2

而不是鎖定'templist',使用全局鎖。然後保護所有代碼修改源列表使用相同的鎖。

另外,也許在旁邊,但等待線程部分完成可以更優雅地完成,即不涉及循環。使用ManualResetEvent將允許您的原始線程等待其他線程中發生「某事」。使用WaitOne會阻塞該線程,直到在另一個線程中調用Set()。

private object m_Lock = new object(); 
private ManualResetEvent m_ResetOne = new ManualResetEvent(false); 
private ManualResetEvent m_ResetTwo = new ManualResetEvent(false); 

(...) 

new Thread(() => FirstMethod(tempList1)).Start(); 
new Thread(() => SecondMethod(tempList2)).Start(); 
m_ResetOne.WaitOne(); 
m_ResetTwo.WaitOne(); 

(...) 

private void FirstMethod(List<T> templist) 
{ 
    lock (m_Lock) 
    { 
     var temp = new T[templist.Count]; 
     templist.CopyTo(temp); 
    } 
    m_ResetOne .Set(); 
    //moves on 
} 
+0

手動重置看起來不錯,會嘗試在某個地方,但在這個特殊的問題,不幸的是不會幫助,因爲我真的真的過分簡化了例子中的東西。但是我學到了一些新的東西,謝謝! –

0

您需要某種類型的同步機制來防止List<T>被更改。我們在當前樣本中看不到足夠的代碼,以保證它不會被更改。