1

我知道这听起来可能很奇怪,但是是的,现在是 2009 年,我需要使用 BCB5 编写小型应用程序 :)

问题是 DynamicArray 在尝试从工作线程中扩展它时抛出 OutOfBound 异常。

我有全局变量,比方说

DynamicArray<double> X;

在主线程中,我检查数组的长度,我得到 0,这没关系(长度未设置)

Application->MessageBox(itoa(X.Length,str , 10), "", MB_OK);

下面是我的工作线程类

class ArrayModifierThread : public TThread
{
private:
DynamicArray<double> __thread X;

protected:
void __fastcall Execute();

public:
__fastcall ArrayModifierThread(bool CreateSuspended);
 void setX(DynamicArray<double> &a);
};

到目前为止,一切都很好。接下来我创建新线程:

ArrayModifierThread *t = new ArrayModifierThread(true);
t->setX(X); // Pass reference to my global DynamicArray
t->Resume();

这里 Execute() 方法被执行:

void __fastcall ArrayModifierThread::Execute()
{
 X.Length = 10;
 X[5] = 45.5;
}

我期望的是全局数组被扩展,第 6 个元素的值为 45.5。

但是从主线程中进行更仔细的调查会给出 Length = 0 和 ArrayOfBounds 异常:

 Application->MessageBox(itoa(__X.Length,str , 10), "", MB_OK);
 Application->MessageBox(itoa(__X[5],str , 10), "", MB_OK);

谁能告诉我我错过了什么?

4

3 回答 3

1

它不起作用,因为成员 X 不是参考。当您调用 set() 时,您正在制作对象的本地副本,然后 Execute() 正在修改本地版本。

class ArrayModifierThread : public TThread
{
    private:
        DynamicArray<double> __thread X;


void __fastcall ArrayModifierThread::Execute()
{
    X.Length = 10;
    X[5] = 45.5;
 }

有三种替代解决方案:

使您的本地成员变量 X 成为引用。
由于引用必须在构造时初始化,您不能使用 set() 修改它,因此将引用传递给对象的构造函数并将其保存在那里。

使您的本地成员变量 X 成为指针。使用 set() 时,获取传入参数的地址(注意它是一个引用,因此您将获得它所引用的对象的地址)。这也意味着需要修改执行以考虑到 X 是一个指针。

不要使用局部成员变量。直接修改全局即可。

于 2009-02-03T14:19:19.847 回答
1

在您的Execute方法中,您正在修改线程的 X字段,而不是全局X变量。尽管该setX方法通过引用接收其参数,但成员变量不是引用。它存储值的副本DynamicArray更改Length属性可确保它引用唯一的数组。

正如您在“答案”中正确观察到的那样,该setX函数接收对全局变量的引用,但它不保留对它的引用。X相反,它在分配对象的字段时会复制它。

也许您也打算声明X为参考:

private:
  DynamicArray<double>& X;

那可以工作。您的setX函数将不再起作用,因为您不允许在初始化后“重新设置”引用。相反,您需要在线程的构造函数中对其进行初始化:

ArrayModifierThread(DynamicArray<double>& a): X(a) { ... }

您还可以存储指向数组的指针而不是引用:

private:
  DynamicArray<double>* X;
public:
  void setX(DynamicArray<double>& a) {
    X = &a;
  }
protected:
  void Execute() {
    X->Length = 10;
    (*X)[5] = 45.5;
  }

您需要注意的另一件事是您的代码不是线程安全的。(这里也不是我的。)您有多个线程修改相同的共享资源(数组)而没有任何保护,例如临界区。不过,这超出了这个问题的范围。首先搜索 Stack Overflow 和 Web 的其余部分,如果您需要有关该问题的帮助,然后再回来提出新问题。

于 2009-02-03T07:33:39.773 回答
0

嗯,这对我来说不是很清楚。我认为由于 void setX(DynamicArray &a) 工作线程获得了对全局变量的引用。

您能否发布示例代码应该如何完成?

这就是我的 void setX(DynamicArray &a) 的样子:

void ArrayModifierThread::setX(DynamicArray<double> &a)
{
   X = a;
}
于 2009-02-03T07:43:50.610 回答