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

时间:2017-11-01 21:26:00

标签: c++ multithreading callback c++-cli

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

我有两个类:MyForm,对应于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运行时使用.flex-info { color: white; font-family: 'Arial', sans-serif; font-size: 16px; box-shadow: 0px 2px 1px rgba(0,0,0,0.2); padding: 10px; border-radius: 2px; width: 20%; height: 100px; text-align: center; } .flex-info.green { background: #79B0B4; } .flex-info.blue { background: #7993B4; } .flex-info.foam { background: #79B47D; } .flex-info.pink { background: #9B79B4; } .flex-info.red { background: #B4797F; }更新UI。

最好的方法是什么?由于CLI,简单地传递函数指针不起作用。

1 个答案:

答案 0 :(得分:0)

我已经开始工作了。然而,正如@Hans Passant指出的那样,这几乎模仿了BackgroundWorker的行为。无论如何,下面是最热门问题的答案,没有使用BackgroundWorker。但感觉不是很干净。

正如@ orhtej2所指出的,a delegate is what's needed。要使上述两个头文件都能识别它,我必须在stdafx.h中声明委托(如建议的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.
            //...
        }