所以我有一个获取List of the Dictionary< myObj>的方法,然后遍历字典的键并传递每个List< myObj>到另一个线程。
以下是一些Code / Psuedo-Code:
public static void ProcessEntries() {
Dictionary<string, List<myObj>> myDictionary = GetDictionary();
foreach(string key in myDictionary.keys)
{
List<myObj> myList = myDictionary[key];
Thread myThread = new System.Threading.Thread(new System.Threading.ThreadStart(delegate() {
ProcessList(myList);
}
}
}
public static void ProcessList(List<myObj> myList) {
// Process entries
// read-only operations on myList
}
问题是在执行ProcessList期间,myList参数只会改变。
我在线程开始之前已遍历列表,然后立即在线程内部,我发现结果不同。
我已经通过使Dictionary变量全局解决了问题(我认为!)。使用[ThreadStatic]属性是可能修复列表的下一个。
我真正想知道的是为什么myList对象在ProcessList()内部发生变化,大概是在ProcessEntries()中重新分配myList对象的时候?这些不是两个不同的列表吗?如果默认情况下所有参数传递都是值,为什么ProcessList()函数没有myList的本地副本? (是吗?)
有没有办法指定您希望将参数传递给线程,而不是在执行期间由父线程或其他线程更改? (这类似于全局变量的[ThreadSafe]属性)
答案 0 :(得分:2)
我怀疑你的伪代码实际上并不是你真实代码的准确反映。我怀疑你的真正的代码如下所示:
foreach(var pair in myDictionary)
{
Thread myThread = new Thread(delegate() {
ProcessList(pair.Value);
});
myThread.Start();
}
如果是这种情况,问题是正在捕获pair
变量 - 所以当你的线程开始时,它可能指的是不同的键/值对。
修复它的方法是使代码更像伪代码:
foreach(var pair in myDictionary)
{
// You'll get a new list variable on each iteration
var list = pair.Value;
Thread myThread = new Thread(delegate() {
ProcessList(list);
});
myThread.Start();
}
有关详细信息,请参阅Eric Lippert's blog post on this。
如果这不是出错的地方,请提供真实的示例,而不是伪代码。 short but complete example demonstrating the problem是理想的。
答案 1 :(得分:1)
还要确保其他线程不会影响您尝试使用的线程。一定要使用锁和监视器...几周之前就有一些问题..
答案 2 :(得分:0)
在这种情况下,您按值传递引用,因此如果您在某处修改它,那么每个地方都会有所不同。