Passing callback function to thread in C++/CLI
Some context: I know basic C++. For the first time, I'm trying to create GUI application in Visual Studio using C++/CLI. However, I can't find much answers online about the latter.
I've got to classes: MyForm
, the main class corresponding to a Windows Form, and OtherClass
. MyForm
has an object of type OtherClass
as a member. A function of MyForm
, in this example myButton_Click
, initializes this object and calls one of its function in a thread:
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;
}
};
This seems to be working, so far. What I want is to pass some kind of callback function from MyClass
to o->foo
to update the UI with values from foo
while it's running.
What's the best way to do this? Simply passing function pointers doesn't work because of CLI.
I've got it working. However, as pointed out by @Hans Passant, this is pretty much mimicking the behavior of a BackgroundWorker
. Anyway, below is the answer to the top question, without using a BackgroundWorker
. It feels not very clean, though.
As pointed by @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), for example like this:
delegate void aFancyDelegate(System::String^);
I then passed such a delegate to the constructor of OtherClass, so the object initialization line in MyForm
changed from
o = gcnew OtherClass;
to
aFancyDelegate^ del = gcnew aFancyDelegate(this, &MyForm::callbackFunction);
o = gcnew OtherClass(del);
.
Lastly, to be able to update UI elements from callbackFunction
, even if it was called from another thread, it had to include something like this, as suggested in 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.
//...
}
链接地址: http://www.djcxy.com/p/27812.html