所以我看到 有趣的 玩线程的东西。
我有一个方法可以启动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之间,基本列表以某种方式由某种东西改变。
这些列表是在调用者线程内创建的,并且在线程启动后实际上没有使用,所以我绝对 否 想法如何/为什么会发生这种情况。
毫无疑问,我在这里做错了什么,但我的诺言技巧不会让我看到,任何帮助都会受到赞赏。
答案 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
}
答案 1 :(得分:1)
您发布的代码中没有任何内容表明您做错了什么。问题必须放在其他地方 - 正如评论者所建议的那样,在填充List1 / List2的代码中。如果您正在进行线程处理,也许您还没有等待该线程在继续之前完成填充列表?
答案 2 :(得分: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
}
答案 3 :(得分:0)
您需要某种类型的同步机制来阻止List<T>
被更改。我们在当前样本中看不到足够的代码以保证它不会被更改。