所以我有一个方法,可以获取 List
这是一些代码/伪代码:
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 对象在 ProcessEntries() 中重新分配时,为什么 myList 对象会在 ProcessList() 内发生变化?这不是两个不同的列表吗?如果默认情况下所有参数传递都是按值传递,为什么 ProcessList() 函数没有 myList 的本地副本? (是吗?)
有没有办法指定要将参数传递给线程,并且在执行过程中不让父线程或其他线程更改它? (这类似于全局变量的 [ThreadSafe] 属性)
我怀疑您的伪代码实际上并不能准确反映您的真实代码。我怀疑你的real代码看起来像这样:
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 的博客文章了解更多信息。
,因此,如果您在某处对其进行修改,则各处都会有所不同。