线程参数在线程执行期间发生变化 - 为什么?
所以我有一个方法,获取 List
的 Dictionary
,然后循环遍历字典的键并传递每个 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 Thread(new ThreadStart(delegate()
{
ProcessList(myList);
}
}
}
public static void ProcessList(List<myObj> myList)
{
// Process entries
// read-only operations on myList
}
问题是在执行 ProcessList 期间,myList 参数只是发生了变化。
我在启动线程之前循环遍历了列表,然后立即在线程内部循环,我发现结果是不同的。
我已经通过将 Dictionary
变量设置为全局来解决了这个问题(我认为!)。使用 [ThreadStatic]
属性是可能的修复列表中的下一个。
我真正想知道的是为什么 myList
对象在 ProcessList()
内发生变化大概是当 myList
对象在 中重新分配时>ProcessEntries()
?这不是两个不同的List
吗?如果默认情况下所有参数传递都是按值传递,为什么 ProcessList()
函数没有 myList
的本地副本? (是吗?)
有没有一种方法可以指定您想要将参数传递给线程,并且在执行期间不让它被父线程或其他线程更改? (这类似于全局变量的 [ThreadSafe] 属性)
So I have a method that gets a Dictionary
of List<myObj>
, then cycles through the keys of the dictionary and passes each List<myObj>
to a separate thread.
Here is some 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 Thread(new ThreadStart(delegate()
{
ProcessList(myList);
}
}
}
public static void ProcessList(List<myObj> myList)
{
// Process entries
// read-only operations on myList
}
The problem is that during execution of ProcessList
the myList
parameter simply changes.
I have looped through the list before kicking of the thread, and then immediately inside the thread, and I've found the results to be different.
I have since solved the problem (I think!) by making the Dictionary
variable global. Using the [ThreadStatic]
property is next on the list of possible fixes.
What I really want to know is why does the myList
object changes inside ProcessList()
presumably when the myList
object is re-assigned in ProcessEntries()
? Are these not two different Lists
? If all parameter passing is by value by default, why does the ProcessList()
function not have a local copy of myList
? (does it?)
Is there a way to specify that you want to pass a parameter to a thread and not have it be altered by the parent thread or other threads during execution? (This would be similar to the [ThreadSafe]
attribute for global variables)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
我怀疑您的伪代码实际上并不能准确反映您的真实代码。我怀疑你的真实代码看起来像这样:
如果是这样的话,问题是
pair
变量被捕获 - 所以当你的线程启动时,它可能是引用不同的键/值对。修复它的方法是使代码更像伪代码:
请参阅 Eric Lippert 对此的博客文章了解更多信息。
如果这不是问题所在,请给出一个真实示例而不是伪代码。 简短但完整的示例演示该问题将是理想的选择。
I suspect your pseudo-code isn't actually an accurate reflection of your real code. I suspect your real code looks like this:
If that's the case, the problem is that the
pair
variable is being captured - so by the time your thread starts, it may be referring to a different key/value pair.The way to fix it is to make the code precisely more like your pseudo-code:
See Eric Lippert's blog post on this for more information.
If this isn't what's going wrong, please give a real example rather than pseudo-code. A short but complete example demonstrating the problem would be ideal.
在这种情况下,您将按值传递引用,因此如果您在某处对其进行修改,则各处都会有所不同。
You are passing a reference by value in that case, so if you modify it somewhere it will be different everywhwere.
还要确保其他线程不会影响您尝试使用的线程。一定要使用锁和监视器...几周前遇到了一些问题..
Also be sure that other threads don't affect the thread you're trying to use. be sure to use locks and monitors... Had some issues with that just few weeks ago..