在 C++/CLI 中将回调函数传递给线程
Passing callback function to thread in C++/CLI
一些背景:我知道基本的 C++。我第一次尝试使用 C++/CLI 在 Visual Studio 中创建 GUI 应用程序。但是,我在网上找不到太多关于后者的答案。
我有两个 classes:MyForm
,主要 class 对应于 Windows 表格,以及 OtherClass
。 MyForm
有一个 OtherClass
类型的对象作为成员。 MyForm
的函数,在本例中 myButton_Click
,初始化此对象并在线程中调用其函数之一:
using namespace System::Threading;
ref class MyForm;
ref class OtherClass;
public ref class MyForm : public System::Windows::Forms::Form {
public:
//...
private:
OtherClass^ o;
System::Void myButton_Click(System::Object^ sender, System::EventArgs^ e) {
//When the button is clicked, start a thread with o->foo
o = gcnew OtherClass;
Thread^ testThread = gcnew Thread(gcnew ThreadStart(o, &OtherClass::foo));
newThread->Start();
}
};
ref class OtherClass {
public:
void foo() {
//Do some work;
}
};
到目前为止,这似乎有效。我想要的是 将某种回调函数从 MyClass
传递到 o->foo
以使用 foo
的值更新 UI 而这是 运行.
最好的方法是什么?由于 CLI,简单地传递函数指针是行不通的。
我已经开始工作了。然而,正如@Hans Passant 所指出的,这几乎是在模仿 BackgroundWorker
的行为。不管怎样,下面是最上面的问题的答案,没有使用 BackgroundWorker
。不过感觉不是很干净
正如@orhtej2 所指出的,a delegate
is what's needed. For both of the above header files to recognize it, I had to declare the delegate in stdafx.h
(as suggested here),例如:
delegate void aFancyDelegate(System::String^);
然后我将这样一个委托传递给了 OtherClass 的构造函数,所以 MyForm
中的对象初始化行从
o = gcnew OtherClass;
到
aFancyDelegate^ del = gcnew aFancyDelegate(this, &MyForm::callbackFunction);
o = gcnew OtherClass(del);
.
最后,为了能够从 callbackFunction
更新 UI 元素,即使它是从另一个线程调用的,它也必须包含这样的内容,如 this answer 中所建议的:
void callbackFunction(String^ msg) {
//Make sure were editing from the right thread
if (this->txtBox_Log->InvokeRequired) {
aFancyDelegate^ d =
gcnew aFancyDelegate(this, &MyForm::callbackFunction);
this->Invoke(d, gcnew array<Object^> { msg });
return;
}
//Update the UI and stuff here.
//...
}
一些背景:我知道基本的 C++。我第一次尝试使用 C++/CLI 在 Visual Studio 中创建 GUI 应用程序。但是,我在网上找不到太多关于后者的答案。
我有两个 classes:MyForm
,主要 class 对应于 Windows 表格,以及 OtherClass
。 MyForm
有一个 OtherClass
类型的对象作为成员。 MyForm
的函数,在本例中 myButton_Click
,初始化此对象并在线程中调用其函数之一:
using namespace System::Threading;
ref class MyForm;
ref class OtherClass;
public ref class MyForm : public System::Windows::Forms::Form {
public:
//...
private:
OtherClass^ o;
System::Void myButton_Click(System::Object^ sender, System::EventArgs^ e) {
//When the button is clicked, start a thread with o->foo
o = gcnew OtherClass;
Thread^ testThread = gcnew Thread(gcnew ThreadStart(o, &OtherClass::foo));
newThread->Start();
}
};
ref class OtherClass {
public:
void foo() {
//Do some work;
}
};
到目前为止,这似乎有效。我想要的是 将某种回调函数从 MyClass
传递到 o->foo
以使用 foo
的值更新 UI 而这是 运行.
最好的方法是什么?由于 CLI,简单地传递函数指针是行不通的。
我已经开始工作了。然而,正如@Hans Passant 所指出的,这几乎是在模仿 BackgroundWorker
的行为。不管怎样,下面是最上面的问题的答案,没有使用 BackgroundWorker
。不过感觉不是很干净
正如@orhtej2 所指出的,a delegate
is what's needed. For both of the above header files to recognize it, I had to declare the delegate in stdafx.h
(as suggested here),例如:
delegate void aFancyDelegate(System::String^);
然后我将这样一个委托传递给了 OtherClass 的构造函数,所以 MyForm
中的对象初始化行从
o = gcnew OtherClass;
到
aFancyDelegate^ del = gcnew aFancyDelegate(this, &MyForm::callbackFunction);
o = gcnew OtherClass(del);
.
最后,为了能够从 callbackFunction
更新 UI 元素,即使它是从另一个线程调用的,它也必须包含这样的内容,如 this answer 中所建议的:
void callbackFunction(String^ msg) {
//Make sure were editing from the right thread
if (this->txtBox_Log->InvokeRequired) {
aFancyDelegate^ d =
gcnew aFancyDelegate(this, &MyForm::callbackFunction);
this->Invoke(d, gcnew array<Object^> { msg });
return;
}
//Update the UI and stuff here.
//...
}