线程参数在线程执行期间发生变化 - 为什么?

发布于 2024-09-13 09:35:10 字数 1205 浏览 3 评论 0原文

所以我有一个方法,获取 ListDictionary,然后循环遍历字典的键并传递每个 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

微凉 2024-09-20 09:35:10

我怀疑您的伪代码实际上并不能准确反映您的真实代码。我怀疑你的真实代码看起来像这样:

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 对此的博客文章了解更多信息。

如果这不是问题所在,请给出一个真实示例而不是伪代码。 简短但完整的示例演示该问题将是理想的选择。

I suspect your pseudo-code isn't actually an accurate reflection of your real code. I suspect your real code looks like this:

foreach(var pair in myDictionary)
{
    Thread myThread = new Thread(delegate() {
        ProcessList(pair.Value);
    });
    myThread.Start();
}

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:

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();
}

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.

玻璃人 2024-09-20 09:35:10

在这种情况下,您将按值传递引用,因此如果您在某处对其进行修改,则各处都会有所不同。

You are passing a reference by value in that case, so if you modify it somewhere it will be different everywhwere.

小情绪 2024-09-20 09:35:10

还要确保其他线程不会影响您尝试使用的线程。一定要使用锁和监视器...几周前遇到了一些问题..

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..

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文