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

标签 c# multithreading parameter-passing threadstatic

所以我有一个获取 List 字典的方法,然后循环遍历字典的键并将每个 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] 属性)

最佳答案

我怀疑您的伪代码实际上并不能准确反射(reflect)您的真实代码。我怀疑您的真实代码如下所示:

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会很理想。

关于C# 线程参数在线程执行期间发生变化 - 为什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3417092/

相关文章:

c# - linq to sql返回 bool 值

c# - Interlocked 是否保证对 C# 中其他线程的可见性,还是我仍然必须使用 volatile?

delphi - OleDB:无法绑定(bind) DBTYPE_WSTR 参数 - 出现 DB_E_UNSUPPORTEDCONVERSION 错误

Javascript 函数调用另一个函数作为参数

c# - 随机洗牌列表

c# - 何时/如何使用 SQL Server XML 数据类型?

java - 同时创建新文件

java - 当线程访问时,矩阵打印得不好

multithreading - 让多个线程将相同的值写入相同的变量是否可以?

c++ - 即使在 Visual C++ 编译器中,在模板中传递 "const char"参数时也会遇到一些问题 Nov 2013 CTP