在 C++/CLI 中将回调函数传递给线程

Passing callback function to thread in C++/CLI

一些背景:我知道基本的 C++。我第一次尝试使用 C++/CLI 在 Visual Studio 中创建 GUI 应用程序。但是,我在网上找不到太多关于后者的答案。

我有两个 classes:MyForm,主要 class 对应于 Windows 表格,以及 OtherClassMyForm 有一个 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.
            //...
        }