2011-09-01 120 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>被更改。我们在当前样本中看不到足够的代码,以保证它不会被更改。