为什么捕获的变量没有持有对象实例的引用

时间:2010-08-31 13:08:31

标签: c# delegates foreach closures invoke

如下面的代码所示,我在foreach循环中创建一个线程并在以后运行它们,但是当我运行该线程时,我得到“对象引用未设置为对象的实例”错误。我怀疑这是一个闭包问题,但似乎我正在做的一切我应该通过创建值的本地副本来避免这一点。如何更正此代码以完成线程的创建,然后在以后允许调用方法(线程启动)?

foreach (ObjWithDelegateToCreateTrdFrom item in queryResult)
{
    // Capture object state    
    ObjWithDelegateToCreateTrdFrom capturedValue = item;

    // Create thread from object
    Thread thread = new Thread(() =>
    {
        capturedValue.Method.Invoke(capturedValue.paramsArray)
    });

    // Add thread to temp thread list
    trdList.Add(thread);
}

2 个答案:

答案 0 :(得分:2)

检查以下值:

  1. capturedValue
  2. capturedValue.Method
  3. capturedValue.paramsArray
  4. 在lambda体中,即在执行线程时。

    即使它们在您创建线程时不是null,也可以在初始化线程对象和运行时决定执行它之间将它们设置为null。

答案 1 :(得分:1)

试试这个:

foreach (ObjWithDelegateToCreateTrdFrom item in queryResult)
{
    if (item == null)
    {
        throw new InvalidOperationException("Item is null");
    }

    if (item.Method == null)
    {
        throw new InvalidOperationException("Item.Method is null");
    }

    if (item.paramsArray == null)
    {
        throw new InvalidOperationException("Item.paramsArray is null");
    }

    // Create thread from object
    Thread thread = new Thread(() =>
    {
        capturedValue.Method.Invoke(capturedValue.paramsArray)
    });

    // Add thread to temp thread list
    trdList.Add(thread);
}

如果这不能解决您的问题,请给我们一个包含更多信息的堆栈跟踪。