gpt4 book ai didi

multithreading - C++/CLI 线程 - InvalidProgramException

转载 作者:行者123 更新时间:2023-12-03 13:17:28 25 4
gpt4 key购买 nike

我正在使用 C++/CLI 编写一种下载器。它应该在进度条中显示下载状态。为了让下载不阻塞表单,我需要在后台线程中运行它,但是为了访问进度条,我需要在我的下载函数中指向它的指针。因此,我需要以表单(或进度条,无所谓)作为参数来启动线程。为此,我编写了一个小线程包装类:

typedef System::Collections::Generic::List<System::Object^> ArgList;

ref class GCThread {

private:
void (*entryPoint)(System::Object^);
ArgList^ arguments;
public:
GCThread(void (*entryPoint)(System::Object^)) { this->entryPoint = entryPoint; arguments = gcnew ArgList(); };
void addArgument(System::Object^ obj) { arguments->Add(obj); };
void start();
};

void GCThread::start() {

System::Threading::ParameterizedThreadStart^ ts = gcnew System::Threading::ParameterizedThreadStart(&entryPoint);
System::Threading::Thread^ t = gcnew System::Threading::Thread(ts);
t->Start((System::Object^) arguments);
}

当尝试像这样调用函数时
GCThread^ thread = gcnew GCThread(downloadFiles);
thread->addArgument(btnLogin);
thread->addArgument(pgrDownload);
thread->start();

downloadFiles 是一个全局方法,定义为
void __clrcall downloadFiles(System::Object^);

我得到一个 System::InvalidProgramException: The Common Language Runtime has found an invalid program 在创建参数化线程启动对象时。我究竟做错了什么?为什么不能为 gc 类型创建全局变量?我知道拥有全局变量完全违背垃圾收集器的目的,但至少有机会自己决定会很好。

顺便说一句,我使用的是 VC++ 2008。
谢谢你的时间!

最佳答案

  ... ts = gcnew System::Threading::ParameterizedThreadStart(&entryPoint)

你欺骗了编译器接受一个无效的程序。该方法需要一个委托(delegate)对象,您传递了一个非托管函数指针。这是编译器中的一个缺陷,它应该生成一个诊断。值得注意的是 IntelliSense 解析器确实会提示。当您删除 & 运算符时,它会变得更加壮观,这会导致编译器崩溃。可能应该为此使用正确的名称:编译器错误。

您需要通过使用 delegate 关键字声明正确的委托(delegate)类型来取得成功。重写你的代码(我认为)做你想做的事:
using namespace System;

typedef System::Collections::Generic::List<System::Object^> ArgList;

ref class GCThread {
public:
delegate void EntryPoint(ArgList^ args);
private:
EntryPoint^ entryPoint;
ArgList^ arguments;
void startFunc(Object^ args);
public:
GCThread(EntryPoint^ start) { this->entryPoint = start; arguments = gcnew ArgList(); };
void addArgument(System::Object^ obj) { arguments->Add(obj); };
void start();
};

void GCThread::startFunc(Object^ args) {
this->entryPoint(safe_cast<ArgList^>(args));
}

void GCThread::start() {
auto t = gcnew System::Threading::Thread(gcnew System::Threading::ParameterizedThreadStart(this, &GCThread::startFunc));
t->Start(arguments);
}

示例用法:
void ExampleThread(ArgList^ args) {
// etc..
}
....
auto t = gcnew GCThread(gcnew GCThread::EntryPoint(&ExampleThread));
t->addArgument(42);
t->start();

较不痛苦的方法是只声明一个简单的类类型,它只存储参数并使用普通线程。在线程函数中使用 safe_cast<> 来恢复参数。在您的情况下甚至不需要,因为您想使用 List<>。换句话说:
void ExampleThread(Object^ arg) {
auto args = safe_cast<List<Object^>^>(arg);
// etc...
}
...

auto arg = gcnew List<Object^>;
arg->Add(42);
auto t2 = gcnew Thread(gcnew ParameterizedThreadStart(&ExampleThread2));
t2->Start(arg);

关于multithreading - C++/CLI 线程 - InvalidProgramException,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24824460/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com